Modelul Saga și tranzacțiile distribuite
Tiparul saga și tranzacțiile distribuite
1) De ce sunt necesare sagas
2PC clasic (cu două faze de blocare) este slab scalabil, complex sub eșecuri și blochează resursele. Saga descompune procesul general de afaceri într-o secvență de tranzacții locale (pași), fiecare dintre care se angajează independent. În caz de eșec, etapele ulterioare sunt anulate, iar cele care au fost deja finalizate sunt compensate prin operațiuni inverse.
Rezultatul: a gestionat eventuala consecvență fără blocare globală, supraviețuire ridicată și un protocol clar de recuperare.
2) Modele de bază
2. 1 Orchestraţie
Un coordonator dedicat saga gestionează pașii: trimite comenzi, așteaptă răspunsuri/evenimente, inițiază compensații.
Pro: control centralizat, observabilitate simplă, termene explicite. Contra: Componentă opțională.
2. 2 Coregrafie
Nici un coordonator; serviciile răspund la evenimentele celuilalt („ComandăPlasat” → „PlatăCapturat” → „InventarRezervat”...).
Pro: Conectivitate slabă. Contra: mai greu de urmărit, risc de „dans al morții” fără reguli clare.
2. 3 TCC (Încercați-Confirmare/Anulare)
Opțiunea cu resurse de „înghețare”:1. Încercați - pregătire/rezervă,
2. Confirmați - fixare,
3. Anulare - rollback.
Garanțiile sunt mai mari, dar contractele și termenele de rezervă sunt mai complicate.
3) Pas și contracte de compensare
Fiecare pas = tranzacție locală + compensare (idempotent, permite repetarea).
Compensația nu este necesară pentru a „returna lumea” - echivalența domeniului este suficientă (de exemplu, „plata returnării” în loc de „ștergerea plății”).
Definiți invarianții: pentru bani - soldul nu intră în minus; pentru comenzi - nici un statut „atârnat”.
Introduceți termene limită/rezerve TTL și un „colector de gunoi” pentru încercări restante.
4) Consistența și semantica de livrare
Livrare mesaj: cel puțin o dată (implicit) → toate operațiunile trebuie să fie idempotente.
Ordine: important prin cheie de corelare (ex. 'order _ id',' player _ id').
Exact-o dată nu este scopul saga; realizăm o uniformitate eficientă prin chei idempotente, outbox/inbox și angajarea corectă.
5) Starea saga și jurnalul său
Ce se păstrează:- 'saga _ id',' corelation _ id', status curent (Running/Finalized/Compensating/Compensated/Failed),
- pas și variabilele sale (ID-uri de plată/rezervă)
- istoricul (jurnalul) evenimentelor/deciziilor, marcajelor temporale, termenelor limită, numărul de retribuiri.
- Un Saga Store separat (tabel/document) disponibil coordonatorului.
- Pentru coregrafie - „agenții” locali ai saga, publicarea evenimentelor de stare într-un subiect comun.
6) Modele de publicare fiabile: outbox/inbox
Outbox: pasul comite schimbarea și scrie evenimentul/comanda la tabelul outbox într-o singură tranzacție; lucrătorul publică în anvelopă.
Inbox: consumatorul menține un tabel de "message _ id' procesat → dedup + idempotency.
După un efect secundar de succes comite offset/ACK (Kafka/RabbitMQ) - nu mai devreme.
7) Proiectarea etapelor saga
7. 1 Exemplu (cumpărare iGaming/e-commerce)
1. PlaceOrder → status 'ÎN AȘTEPTARE'.
2. AuthorizePayment (Try) → 'payment _ hold _ id'.
3. ReserveInventory → 'reservation _ id'.
4. CapturePayment (Confirmare).
5. FinalizeOrder → 'FINALIZAT'.
- dacă (3) → "CancelPaymentHold' eșuează;
- (4) eșuat după (3) → „ReleaseInventory”;
- dacă (5) → „RambursarePlată” și „ReleaseInventory” eșuează.
7. 2 Termene limită/Retrageri
Refaceri maxime N cu întârziere exponențială + jitter.
După depășirea - du-te la „Compensarea”.
Păstrați next_attempt_at și deadline_at pentru fiecare pas.
8) Orchestrator vs platformă
Opțiuni:- Orchestrator de acasă ușor (masă microservice + Saga).
- Platforme: Temporal/Cadence, Camunda, Netflix Conductor, Zeebe - da cronometre, retray-uri, fluxuri de lucru de lungă durată, vizibilitate și o consolă web.
- Pentru coregrafie, utilizați un catalog de evenimente și o convenție strictă de stare/cheie.
9) Protocoale de integrare
9. 1 Asincron (Kafka/RabbitMQ)
Comenzi: "plăți. autoriza. v1 ', "inventar. rezervă. v1 '.
Evenimente: 'plăţi. autorizat. v1 ', "inventar. rezervat. v1 ', "plăţi. capturat. v1 ', "plăţi. rambursate. v1 '.
Part key = 'order _ id'/' player _ id' pentru comandă.
9. 2 Sincron (HTTP/gRPC) într-o etapă
Valabil pentru pași „scurți”, dar întotdeauna cu timeout/retroys/idempotency și rezervă la compensare asincronă.
10) Idempotence și chei
În cererile de comandă și compensare, treceți 'idempotency _ key'.
Efectele secundare (scrierea la baza de date/scrierea off) sunt efectuate condiționat: „efectua dacă nu ați văzut încă” idempotency _ key „”.
Compensația este, de asemenea, idempotentă: repetarea 'RambursarePlată (id = X)' este sigură.
11) Manipularea erorilor
Clase:- Tranzitoriu (rețele/timeout-uri) → retray/backoff.
- Întreprinderi (fonduri insuficiente, limite) → compensații imediate/cale alternativă.
- Intervenție irecuperabilă → manuală, compensare manuală.
- Construiți o matrice de soluție: tipul de eroare → acțiune (încercați din nou/compensați/escaladați).
12) Observabilitate și SLO sag
SLI/SLO:- Latența finală a saga (p50/p95/p99).
- Rata de succes.
- Timpul mediu pentru a compensa rata и compensare.
- Saga orfană şi timpul până la GC.
- Trace: 'trace _ id'/' saga _ id' ca legătură între pași; burn-rate metrics for error budgets.
Jurnale: fiecare schimbare de stare saga = înregistrare structurată cu cauză.
13) Exemple (pseudocod)
13. 1 Orchestrator (idee)
python def handle(OrderPlaced e):
saga = Saga. start(e. order_id)
saga. run(step=authorize_payment, compensate=cancel_payment)
saga. run(step=reserve_inventory, compensate=release_inventory)
saga. run(step=capture_payment, compensate=refund_payment)
saga. run(step=finalize_order, compensate=refund_and_release)
saga. complete()
def run(step, compensate):
try:
step () # local transaction + outbox except Transient:
schedule_retry()
except Business as err:
start_compensation(err)
13. 2 Outbox (ideea tabelului)
outbox(id PK, aggregate_id, event_type, payload, created_at, sent_at NULL)
inbox(message_id PK, processed_at, status)
saga(order_id PK, state, step, next_attempt_at, deadline_at, context JSONB)
saga_log(id PK, order_id, time, event, details)
13. 3 Coregrafie (idei tematice)
orders. plasate „→ consumatori: ” plăți. autoriza „,” inventar. rezervă "
"plăţi. inventar autorizat „+”. rezervate „→” comenzi. try_finalize'
Orice eşec al ordinelor lui →. compensează plățile „→ inițiate”. anulare/rambursare „,” inventar. eliberare ".
14) Comparație cu 2PC și ES
2PC: consistență puternică, dar blocaje, blocaje, țevi de cupru.
Saga: eventual coerență, aveți nevoie de o disciplină de compensare și telemetrie.
Event Sourcing: stochează evenimentele ca sursă de adevăr; sagas pe ea sunt naturale, dar se adaugă complexitate la migrații/instantanee.
15) Siguranță și conformitate
Securitatea transportului (TLS/mTLS), ACL pe subiect/coadă.
În evenimente - cel puțin PII, criptarea câmpurilor sensibile, tokenizarea.
Acces de audit la saga și jurnalele de compensare.
SLA cu furnizori externi (plăți/livrare) = termenul limită și parametrii limită de retransmitere.
16) Lista de verificare a implementării (0-45 zile)
0-10 zile
Selectați procesele candidate (multi-service, compensate).
Selectați modelul (orchestrație/coregrafie/TCC) și cheia de corelare.
Descrieți pașii/compensările, invarianții și termenele limită. Ridicați tabelele „saga”, „outbox”, „inbox”.
11-25 zile
Include outbox/inbox, idempotency, și retrotraces backoff.
Implementați primele sagas; adăugați tablouri de bord SLI/SLO și urme.
Scrieți un runbook de compensații (inclusiv manual) și escaladări.
26-45 zile
Automate GC „agățat” sagas, reporniri periodice/continuări la termen.
Petreceți ziua jocului: eșec pas, exces termen limită, indisponibilitate broker.
Standardizați contractele de evenimente (versiuni, compatibilitate), configurați un „director saga”.
17) Anti-modele
„Compensare = ștergere din baza de date” în loc de acțiune inversă corectă a domeniului.
Fără outbox/inbox → pierderea evenimentelor/efecte duble.
Retrai fără jitter → dependențe de auto-DDoS.
Așteaptă o consistență puternică la citire fără „procesare în curs de desfășurare”....
Un orchestrator gigant pentru toate → monolit de control.
Coregrafie totală fără vizibilitate și SLA → dans incontrolabil.
Ignorarea termenelor limită → rezervele eterne.
18) Valorile maturității
≥ 90% din procesele critice sunt acoperite de sagas/compensații și au invarianții descriși.
Outbox/inbox sunt integrate pentru toți producătorii/consumatorii Tier-0/1.
SLO: p95 saga end-to-end este normală, rata de succes este stabilă, orfană <țintă.
Urmărire transparentă și tablouri de bord „în pași”, alerte arde-rate.
Ziua de joc trimestrială și verificarea manuală a compensării runbook.
19) Concluzie
Saga este un contract practic de coerență pentru sistemele distribuite: pași clari și acțiuni inverse, publicarea disciplinei (outbox/inbox), termene și retribuții, observabilitate și procese de compensare. Alegeți un model (orchestrație/coregrafie/TSS), fixați invarianții și cheile, faceți manipulatorii idempotenți - iar procesele dvs. de afaceri multiservice vor deveni previzibile și stabile fără 2PC costisitoare.