Sagas y transacciones distribuidas
La saga es una transacción empresarial a largo plazo, dividida en una secuencia de pasos locales en diferentes servicios/almacenamiento. Cada paso tiene una acción compensatoria que retrotrae el efecto del paso cuando falla parcialmente. A diferencia de 2PC/3PC, las sagas no mantienen bloqueos globales y son adecuadas para microservicios, multi-regiones y altas cargas, donde la consistencia eventual es permisible.
1) Cuándo elegir sagas (y cuándo no)
Adecuado:- Procesos comerciales largos/de varios pasos (pedido → pago → reserva → entrega).
- Diferentes dominios y almacenes donde no hay transacción compartida.
- Necesita alta disponibilidad y escala horizontal.
- La atomicidad ACID sólida es crítica (por ejemplo, transferir grandes cantidades dentro de un único registro).
- No hay una compensación clara (no se puede «reservar una vez» o cancelar el efecto).
- Las restricciones legales/regulatorias requieren un aislamiento estricto y un invariante «instantáneo».
2) Modelos de sagas
1. Orquesta (Saga Orchestrator): el coordinador central gestiona los pasos y las compensaciones.
Ventajas: flujo explícito, control de errores, telemetría simplificada.
Contras: punto de centralización, riesgo de coordinador «grueso».
2. Coreografía: no hay centro: los pasos son iniciados por eventos («el servicio A hizo X → el servicio B responde»).
Ventajas: conectividad débil, escala simple.
Contras: es más difícil rastrear/desbordar el flujo, el riesgo de «crecer» las reglas.
3. TCC (Try-Conflm/Cancel): cada paso es «Try» (Try), a continuación, confirmación o cancelación (Cancel).
Ventajas: más cerca del protocolo pseudo-bifásico, recursos gestionados.
Contras: más caro en la implementación de interfaces; requiere temporizadores de los titulares de «Try».
3) Diseño de paso y compensación
Invariantes: articular claramente lo que debe ser verdadero «antes/después» del paso (por ejemplo, «residuo ≥ 0»).
Compensación ≠ transacción inversa: es una acción lógica que anula el efecto empresarial (refund, release, restore).
Idempotencia: tanto el paso como el compensador deben repetirse con seguridad (por 'operation _ id').
Timautas: cada paso tiene un deadline; la demora inicia la compensación.
Efectos no reembolsables: fijarlos por separado (notificaciones, e-mail) y permitir el «mejor efecto».
4) Coherencia y orden
Consistencia eventual: los usuarios pueden ver discrepancias temporales; UX - con «espera «/spinners/status.
Orden por clave: agrupe los pasos de conmutación por clave de negocio (order_id) para organizar los eventos.
Deduplicación: almacene el registro de tratamientos ('operation _ id' → estado) con TTL.
5) Transporte y fiabilidad
Pattern de outbox: escribe el evento en la tabla local «outbox» dentro de la misma transacción, y luego la publicación asíncrona en el bus.
Inbox/Idempotency store: del lado del consumidor, el registro de los mensajes ya procesados.
Exactly-once es eficaz: «outbox + idempotent consumer» da práctica «exactamente una vez».
DLQ: para mensajes «venenosos» con una rica información meta y un redrive seguro.
6) Políticas de error, retraídas, backoff
Sólo repetimos los pasos idempotentes; operaciones de grabación - con 'Idempotency-Key'.
Backoff + jitter exponencial; limitar los intentos y el resumen de la saga.
En la degradación del sistema, el Circuit Breaker y la degradación graceful (por ejemplo, cancelar una parte secundaria de la saga).
Conflictos empresariales ('409'): repetición después de la negociación o compensación y finalización.
7) Orquestador: responsabilidades y estructura
Funciones:- Seguimiento del estado de la saga: 'PENDING → RUNNING → COMPENSATING → DONE/FAILED'.
- Planificación de pasos, deduplines, tiempos de espera, retiros.
- Enrutamiento de eventos y lanzamiento de compensaciones.
- Idempotencia de las operaciones del coordinador (registro de comandos).
- Observabilidad: correlación de 'saga _ id' en logs/tries/métricas.
- Tablas 'saga', 'saga _ step', 'comandos', 'outbox'.
- Índices por 'saga _ id', 'business _ key', 'status', 'next _ run _ at'.
8) Coreografía: reglas y protección contra el «coma de nieve»
Contratos de eventos: esquemas y versionados (Avro/Proto/JSON Schema).
Semántica clara: «evento de hecho» vs «comando».
Restos de la cadena: el servicio, tras detectar la discrepancia, publica el evento 'Fallido '/' Compensado'.
Alarmas y alertas a «bucles infinitos».
9) TCC: detalles prácticos
Try: reserva de recursos con TTL.
Confinamiento: fijación, liberación de bloqueos temporales.
Cancel: retroceso de la reserva (sin efectos secundarios).
Colección Garbage: eliminación automática de Try después de TTL (Cancel idempotente).
Confianza/Cancel idempotente: la repetición es segura.
10) Ejemplo (esquema verbal) - «Pedido con pago y envío»
1. CreateOrder (local) → outbox: 'OrderCreated'.
2. PaymentService: reserva 'Try' (TCC); si el → 'PaymentReserved' tiene éxito, cuando el → 'PaymentFailed' falla.
3. InventoryService: reserva de artículos; con la falta de → 'InventoryFailed'.
4. ShippingService: crear una ranura de envío (cancelable).
5. Si cualquier paso 'Fallido' → el orquestador ejecuta las compensaciones en orden inverso: 'CancelShipping' → 'ReleaseInventory' → 'PaymentCancel'.
6. Si todo está cerca de → 'PaymentConflm' → 'OrderConfirmed'.
11) Pseudocódigo del orquestador
pseudo startSaga(saga_id, order_id):
steps = [ReservePayment, ReserveInventory, BookShipment, ConfirmPayment]
for step in steps:
res = execWithRetry(step, order_id)
if!res.ok:
compensateInReverse(steps_done(order_id))
return FAIL return OK
execWithRetry(step, key):
for attempt in 1..MAX:
try:
return step.run(key) # идемпотентно catch RetryableError:
sleep(backoff(attempt))
catch NonRetryableError:
return FAIL return FAIL
compensateInReverse(done_steps):
for step in reverse(done_steps):
step.compensate() # идемпотентно
12) Observabilidad y SLO operativos
Treking: una sola 'saga _ id', anotaciones 'step', 'attempt',' decision '(run/compensate/skip).
Métricas:- Acierto/error de sagas (%), duración media, p95/p99.
- Proporción de sagas compensadas, las principales causas de las indemnizaciones.
- Colas/outbox lags, retiros por pasos.
- Registros/auditorías: soluciones de orquestación, identificadores de recursos, claves de negocio.
13) Pruebas y caos
Inyección de errores en cada paso: tiempos de espera, '5xx', conflictos comerciales.
Eventos fuera de orden, duplicados, pases (drop).
Largas colas de latencia → comprobación de las dedlines y compensaciones.
Sagas masivas → verificación de WFQ/DRR y caps en las colas, sin «bloqueo de cabeza de línea».
Redrive es de DLQ por los pasos y por toda una saga.
14) Multi-tenencia, regiones, conformidad
Etiquetas 'tenant _ id/plan/region' en eventos y repositorios de sagas.
Residencia: los datos/eventos no salen de la región; las sagas transversales regionales diseñan como federaciones de sagas locales + eventos de agregación.
Priorización: las sagas VIP tienen un mayor peso de cuota; aislamiento de los workers per tenant.
15) Lista de verificación antes de la venta
- Cada paso tiene un compensador claro, ambos son idempotentes.
- Plantilla seleccionada: orquestación/coreografía/TSC; se describen los límites de la responsabilidad.
- Outbox/Inbox incrustado, deduplicación por 'operation _ id'.
- Políticas de retraídos: backoff con jitter, límites de intento y saga general de deadline.
- Los contratos de eventos están versionados, hay una validación del esquema.
- El DLQ y el redrive seguro están configurados.
- Telemetría: métricas, senderismo, correlación 'saga _ id'.
- playbooks operativos: cancel/force-confinm manual, descomposición de las sagas «colgantes».
- Las pruebas de caos y carga pasan, SLO/presupuesto de error está definido.
16) Errores típicos
No hay compensador o es «impuro» (tiene efectos secundarios).
Falta idempotencia/dedoop - tomas y «swing» de estados.
«La saga en la saga» sin fronteras explícitas son ciclos y bloqueos mutuos.
No hay deadlines → sagas «eternas» y fugas de recursos.
El orquestador mantiene el estado «en la memoria» sin un sor estable.
La coreografía sin centro de telemetría → fallos «invisibles».
UX opaco: los usuarios no ven estados intermedios.
17) Recetas rápidas
Clásicos de SaaS: orquestación + outbox/inbox, backoff exponencial, DLQ, estados de la saga en IU.
Invariantes fuertes sobre el recurso: TCC con reserva TTL y Cancel GC.
Alto volumen/carga: coreografía de eventos + estricta idempotencia y métricas por clave.
Multi-región: sagas locales + agregados finales; evitar los bloqueos globales.
Conclusión
Las sagas son una forma de obtener consistencia predecible en sistemas distribuidos sin bloqueos globales. Los compensadores claros, la idempotencia, la entrega confiable (outbox/inbox), la disciplina de los timeouts y los retraídos, más la telemetría y los playbooks, son la clave para que los complejos procesos de negocio sigan siendo sostenibles y legibles a la vez que aumentan la carga, el número de servicios y las geografías.