Schemat sagi i transakcje rozproszone
Wzorzec sagi i transakcje rozproszone
1) Dlaczego sagi są potrzebne
Klasyczny 2PC (dwufazowe zatrzaski) jest słabo skalowalny, złożony pod awariami i blokuje zasoby. Saga rozbija cały proces biznesowy na sekwencję transakcji lokalnych (kroki), z których każda zobowiązuje się samodzielnie. W przypadku awarii kolejne kroki są anulowane, a te, które zostały już zakończone, są kompensowane odwrotnymi operacjami.
Wynik: zarządzana ewentualna spójność bez globalnego blokowania, wysoka trwałość i jasny protokół odzyskiwania.
2) Podstawowe modele
2. 1 Orkiestra
Dedykowany koordynator sagi zarządza krokami: wysyła polecenia, czeka na odpowiedzi/zdarzenia, inicjuje kompensacje.
Plusy: scentralizowana kontrola, prosta obserwowalność, wyraźne terminy. Minusy: Składnik opcjonalny.
2. 2 Choreografia
Brak koordynatora; usługi reagują na siebie nawzajem zdarzenia („ Placed →” „Wychwytywane” → „WynalazkZarezerwowane”...).
Plusy: Słaba łączność. Wady: trudniejsze do namierzenia, ryzyko „tańca śmierci” bez jasnych zasad.
2. 3 TCC (spróbuj potwierdzić/anulować)
Wariant z „zamrożeniem” zasobów:1. Spróbuj - przygotowanie/rezerwa,
2. Potwierdź - utrwalenie,
3. Anuluj - rollback.
Gwarancje są wyższe, ale kontrakty i terminy rezerwy są bardziej skomplikowane.
3) Umowy etapowe i kompensacyjne
Każdy krok = transakcja lokalna + rekompensata (idempotent, pozwala na powtarzanie).
Odszkodowanie nie jest wymagane, aby w pełni „zwrócić świat” - równoważność domeny jest wystarczająca (na przykład „płatność zwrotna” zamiast „usuń płatność”).
Zdefiniuj niezmienne: dla pieniędzy - saldo nie wchodzi w minus; dla zamówień - brak statusu „hung”.
Wprowadź terminy/rezerwy TTL i „śmieciarka” dla opóźnionych prób.
4) Spójność i semantyka dostawy
Dostawa wiadomości: co najmniej raz (domyślnie) → wszystkie operacje muszą być idempotent.
Zamówienie: ważne przez klucz korelacji (np. 'order _ id',' player _ id').
Dokładnie raz nie jest celem sagi; osiągamy skuteczną jednolitość poprzez idempotentne klucze, skrzynkę odbiorczą/skrzynkę odbiorczą i poprawne skrócenie.
5) Stan sagi i jej dziennik
Co przechowywać:- 'saga _ id',' correlation _ id', bieżący status (Running/Completed/Compensating/Compensated/Failed),
- krok i jego zmienne (płatności/identyfikatory rezerwy),
- historia (dziennik) zdarzeń/decyzji, znaczniki czasowe, terminy, liczba przekładów.
- Osobny sklep Saga (tabela/dokument) dostępny dla koordynatora.
- Dla choreografii - lokalnych „agentów” sagi, publikowanie wydarzeń o statusie we wspólnym temacie.
6) Niezawodne wzory publikacji: skrzynka odbiorcza/skrzynka odbiorcza
Outbox: krok zobowiązuje się do zmiany i zapisuje zdarzenie/polecenie do tabeli wyników w jednej transakcji; Pracownik publikuje w oponie.
Skrzynka odbiorcza: konsument utrzymuje tabelę przetworzonego 'message _ id' → dedup + idempotence.
Po udanym efekcie ubocznym popełnić offset/ACK (Kafka/RabbitMQ) - nie wcześniej.
7) Projektowanie sagi kroki
7. 1 Przykład (iGaming/zakup e-commerce)
1. Kolejność → status 'OCZEKUJĄCY'.
2. Autoryzowana płatność (spróbuj) → 'payment _ hold _ id'.
3. Inventory → 'reservation _ id'.
4. CapturePayment (Potwierdź).
5. FinalizeOrder → 'COMPLETED'.
- jeżeli (3) „Anuluj” → nie powiedzie się;
- (4) nie powiodło się po (3) → „Spis powszechny”;
- jeśli (5) „Płatność zwrotna” i „Spis” → nie powiodą się.
7. 2 Terminy/rekolekcje
Maksimum N przekłada się z opóźnieniem wykładniczym + jitter.
Po przekroczeniu - przejdź do 'Kompensacja'.
Przechowywać next_attempt_at i deadline_at dla każdego kroku.
8) Orkiestrator vs platforma
Opcje:- Lekki orkiestrator domowy (mikroservice + stół Saga).
- Platformy: Temporal/Cadence, Camunda, Netflix Conductor, Zeebe - dać zegary, przekładki, długotrwałe przepływy pracy, widoczność i konsolę internetową.
- W przypadku choreografii należy użyć katalogu zdarzeń i ścisłej konwencji statusu/klucza.
9) Protokoły integracyjne
9. 1 asynchroniczny (Kafka/RabbitMQ)
Polecenia: 'płatności. autoryzować. v1 „,” inwentarz. rezerwy. v1 ".
Wydarzenia: "płatności. autoryzowany. v1 „,” inwentarz. zastrzeżone. v1 „,” płatności. schwytany. v1 „,” płatności. zwrócone. v1 ".
Klucz części = 'order _ id'/' player _ id' dla zamówienia.
9. 2 Synchroniczne (HTTP/gRPC) w jednym kroku
Ważne dla „krótkich” kroków, ale zawsze z terminami/przekładami/idempotencją i awaryjną kompensacją asynchroniczną.
10) Idempotencja i klucze
W żądaniach polecenia i odszkodowania, pass' idempotence _ key ".
Efekty uboczne (zapisywanie do bazy danych/odpisywanie) są wykonywane warunkowo: „wykonaj, jeśli nie widziałeś jeszcze 'idempotence _ key'”.
Odszkodowanie jest również idempotent: powtarzanie 'Refund Payment (id = X)' jest bezpieczne.
11) Obsługa błędów
Klasy:- Przejściowe (sieci/timeouts) → retray/backoff.
- Biznes (niewystarczające fundusze, limity) → natychmiastowa rekompensata/alternatywna ścieżka.
- Nieodkryta → ręczna interwencja, ręczna rekompensata.
- Zbuduj matrycę rozwiązania: typ błędu → działanie (powtórne/kompensacyjne/escalate).
12) Obserwowalność i SLO sag
SLI/SLO:- Opóźnienie końcowe sagi (p50/p95/p99).
- Wskaźnik sukcesu.
- Średni czas na wyrównanie odszkodowania.
- Osierocone sagi i czas do GC.
- Ślad: 'trace _ id'/' saga _ id' jako łącze przęsła między etapami; mierniki prędkości spalania dla budżetów błędów.
Dzienniki: każda zmiana stanu sagi = zapis ustrukturyzowany z przyczyną.
13) Przykłady (pseudokoda)
13. 1 Orkiestrator (pomysł)
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 (idea tabeli)
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 Choreografia (pomysły tematyczne)
"schorzenia. umieszczone „→ konsumenci: ” płatności. autoryzować „,” inwentarz. rezerwa "
"wypłaty. autoryzowany inwentarz '+'. zarezerwowane zamówienia „→”. try_finalize'
Wszelkie awarie → "rozkazy. rekompensaty „→ zainicjowane” płatności. anulować/zwrócić „,” inwentarz. zwolnienie ".
14) Porównanie z 2PC i ES
2PC: silna konsystencja, ale blokady, wąskie gardła, rury miedziane.
Saga: ewentualna spójność, potrzebujesz dyscypliny odszkodowania i telemetrii.
Event Sourcing: przechowuje wydarzenia jako źródło prawdy; sagi na nim są naturalne, ale dodają złożoności migracji/migawki.
15) Bezpieczeństwo i zgodność
Bezpieczeństwo transportu (TLS/mTLS), ACL na temat/kolejkę.
W zdarzeniach - co najmniej PII, szyfrowanie pól wrażliwych, tokenizacja.
Kontrola dostępu do sagów i dzienników odszkodowawczych.
SLA z zewnętrznymi dostawcami (płatności/dostawy) = terminy i parametry graniczne przekładu.
16) Lista kontrolna wdrażania (0-45 dni)
0-10 dni
Wybierz procesy kandydata (multi-service, compensated).
Wybierz model (orkiestra/choreografia/TCC) i klucz korelacji.
Opisz etapy/potrącenia, niezmienne i terminy. Podnieś tabele 'saga', 'outbox', 'skrzynka odbiorcza'.
11-25 dni
Zawiera skrzynkę odbiorczą/skrzynkę odbiorczą, idempotencję i retrasy backoff.
Wdrożyć pierwsze sagi; dodać deski rozdzielcze SLI/SLO i ślad.
Napisz książkę odszkodowań (łącznie z instrukcją) i eskalacji.
26-45 dni
Zautomatyzuj sagi GC „wiszące”, okresowe wznowienia/kontynuacje w terminie.
Spędzić dzień gry: niepowodzenie kroku, nadmiar terminu, niedostępność brokera.
Standaryzuj kontrakty na zdarzenia (wersje, kompatybilność), skonfiguruj „katalog sagi”.
17) Anty-wzory
„Odszkodowanie = usuń z bazy danych” zamiast działania odwrotnego poprawnego dla domeny.
Brak skrzynki odbiorczej → utrata zdarzeń/podwójne efekty.
Retrai bez jitter → zależność od siebie DDoS.
Oczekiwanie silnej spójności czytania bez „przetwarzania w toku”....
Jeden olbrzymi orkiestrator dla wszystkich → monolit kontroli.
Całkowita choreografia bez widoczności i SLA → niekontrolowany taniec.
Ignorowanie terminów → wieczne rezerwy/posiadłości.
18) Wskaźniki zapadalności
≥ 90% procesów krytycznych jest objętych sagami/kompensacjami i charakteryzuje się opisanymi niezmiennikami.
Outbox/skrzynka odbiorcza są zintegrowane dla wszystkich producentów/konsumentów Tier-0/1.
SLO: p95 end-to-end saga jest normalna, wskaźnik sukcesu jest stabilny, osierocony <target.
Przejrzyste odwzorowanie i deski rozdzielcze „w krokach”, alerty spalania.
Kwartalny dzień gry i ręczna kontrola kompensacji runbook.
19) Wniosek
Saga jest praktycznym kontraktem na spójność dla systemów rozproszonych: jasne kroki i odwrotne działania, dyscyplina wydawnicza (skrzynka odbiorcza/skrzynka odbiorcza), terminy i przekłady, obserwowalność i procesy kompensacyjne. Wybierz model (orkiestra/choreografia/TSS), naprawić niezmienne i klucze, sprawić, że obsługujący idempotent - a procesy biznesowe multiservice staną się przewidywalne i stabilne bez drogich 2PC.