サガと分散トランザクション
Sagaは、さまざまなサービス/リポジトリにまたがる一連のローカルステップに分解された長期的なビジネス取引です。各ステップには補償アクションがあり、部分的な失敗でステップ効果をロールバックします。2PC/3PCとは異なり、サガはグローバルロックを保持せず、マイクロサービス、マルチリージョン、高負荷に適しています。
1)サガを選ぶとき(そしてそうでないとき)
適合:- ロング/マルチステップビジネスプロセス(注文→支払い→予約→配送)。
- 共通のトランザクションがない異なるドメインとリポジトリ。
- 高可用性とスケールアウトが必要です。
- 固体酸性原子性は重要である(例えば、同じレジストリ内で大量に転送する)。
- 明確な補償はありません(「予約」または効果をキャンセルすることはできません)。
- 法的/規制上の制限は、厳密な分離と「即時」不変量を必要とします。
2) Sagasモデル
1.佐賀オーケストレーター-中央コーディネーターがステップと補償を管理します。
長所:明示的なフロー、エラー制御、簡易テレメトリー。
短所:集中ポイント、「脂肪」コーディネーターのリスク。
2.振付(振付):センターなし-ステップはイベントによって開始されます(「service A did X→service B reacts」)。
長所:弱い接続性、簡単なスケーリング。
短所:フローを追跡/デバッグすることはより困難です。
3.TCC (Try-Confirm/Cancel)-各ステップは「Try」、次にConfirmまたはCancelです。
長所:擬似2相プロトコルに近い、管理リソース。
短所:インターフェイスの実装においてより高価です。「Try」ホルダーのタイムアウトが必要です。
3)ピッチおよび補償の設計
不変量:ステップの「before/after」(例えば「remainder ≥ 0」)に何をtrueにすべきかを明記します。
報酬≠逆トランザクション:これは、ビジネス効果(払い戻し、リリース、復元)をキャンセルする論理的なアクションです。
Idempotence:ステップと補償の両方を安全に繰り返す必要があります('operation_id'による)。
タイムアウト:各ステップには期限があります。遅延は補償を引き起こします。
非リターンエフェクト:それらを別々に記録し(通知、電子メール)「、最善の努力」を許可します。
4)一貫性および順序
最終的な一貫性:ユーザーは時間の不一致を見ることができます。UX-「wait「/スピナー/ステータス。
「キーごとの注文」(Order by key)-イベントを注文するために、スイッチング手順をビジネスキー(order_id)でグループ化します。
重複排除-処理ログ('operation_id'→status)をTTLに保存します。
5)交通機関および信頼性
Outboxパターン-同じトランザクション内のローカルoutboxテーブルにイベントを書き込み、非同期にバスにパブリッシュします。
受信トレイ/Idempotencyストア:消費者側-既に処理されているメッセージのログ。
正確に一度効果的に:「outbox+idempotent consumer」は実用的な「正確に一度」を与えます。
DLQ:豊富なメタ情報と安全なredriveを持つ「有毒な」メッセージのために。
6)エラー、リトレイ、バックオフポリシー
私たちは、唯一の同一のステップを繰り返します。書き込み操作-'Idempotency-Key'を使用します。
指数関数バックオフ+ジッタ;佐賀の試みとサマリーの期限を制限します。
全身劣化-サーキットブレーカーと優雅な劣化(例えば、佐賀の二次フィクション部分をキャンセル)。
ビジネス紛争('409')-和解後に再試行するか、補償して終了します。
7)オーケストレーター: 責任と構造
関数:- サーガのステータスを追跡する:'保留中→実行中→補償→完了/失敗'。
- ステップ、締め切り、タイムアウト、リトリートの計画。
- イベントルーティングと補償の開始。
- コーディネーター操作(コマンドログ)のIdempotency。
- Observability:ログ/トレース/メトリックの'saga_id'相関。
- テーブル'saga'、 'saga_step'、 'commands'、 'outbox'。
- 'saga_id'、 'business_key'、 'status'、 'next_run_at'のインデックス。
8)振付: 「雪玉」に対する規則と保護"
イベント契約:スキームとバージョン管理(Avro/Proto/JSONスキーマ)。
明確な意味:「イベントファクト」と「コマンド」。
チェーンの停止:ミスマッチを検出したサービスは、'Failed'/'Compensate'イベントを発行します。
「無限ループ」のアラームとアラート。
9) TCC: 実用的な細部
試してみてください:TTLでリソースリザーブ。
確認:コミット、一時的なロックを解除します。
キャンセル:ロールバックを予約します(副作用なし)。
ガベージコレクション:TTL後のTryの自動キャンセル(idempotent Cancel)。
idempotentの確認/キャンセル:繰り返しは安全です。
10)例(ワードスキーム)-「支払いと配送の注文」
1.CreateOrder (local)→outbox: 'OrderCreated'。
2.PaymentService: 'Try' reserve (TCC);→'PaymentReserved'が失敗した場合、'PaymentFailed'が失敗した場合。
3.InventoryService:製品予約;out of→'InventoryFailed'。
4.ShippingService-配送スロットを作成します(キャンセル可能)。
5.'Failed'ステップ→オーケストレーターが'CancelShipping'→'ReleaseInventory'→'PaymentCancel'という逆順で補償を開始した場合。
6.すべてOK→'PaymentConfirm'→'OrderConfirm'。
11)オーケストレータ擬似コード
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)観測可能性と運用SLO
トレース:単一の'saga_id'、注釈'step'、 'attempt'、' decision'(実行/補償/スキップ)。
メトリクス:- サガの成功/エラー(%)、平均持続時間、p95/p99。
- 補償されたサガのシェア、補償の主な理由。
- キュー/アウトボックスラグ、ステップで再試行。
- ログ/監査:オーケストレータソリューション、リソース識別子、ビジネスキー。
13)テストおよび混乱
各ステップにエラーを注入:タイムアウト、'5xx'、ビジネスの競合。
オーダーメイドのイベント、重複、ドロップ。
遅延の長いテール→締め切りと補償のチェック。
マスサガ→キュー内のWFQ/DRRとキャップのチェック、「head-of-line blocking」がない。
ステップと全体の佐賀でDLQから再描画。
14)マルチテナント、地域、コンプライアンス
タグ'tenant_id/plan/region'イベントとsagaリポジトリ。
居住:データ/イベントは地域を離れません。クロスリージョナルサガは、ローカルサガ+集約イベントの連合として設計されています。
優先順位付け:VIP sagasはより大きいクォータ重量を運びます;テナントあたりの労働者の分離。
15)売り上げ前のチェックリスト
- 各ステップには明確な補償があり、両方ともidempotentです。
- 選択したテンプレート:オーケストレーション/振付/TSS;責任制限が記述されています。
- Outbox/Inboxが実装され、'operation_id'による重複排除。
- リトレイポリシー:ジッタ付きのバックオフ、限界と全体的な佐賀期限を試してみてください。
- イベント契約はバージョン管理され、スキームの検証が行われます。
- DLQとSecure Releaseが設定されています。
- テレメトリー:メトリック、トレース、相関'saga_id'。
- 操作プレイブック:手動キャンセル/強制確認、ロック解除「ハング」サガ。
- カオスとロード・テストのパス、SLO/エラー・バジェット定義。
16)典型的なエラー
補償がないか、それは「汚れている」(副作用があります)。
2倍の状態と「スイング」状態の偶像性/デッドアップはありません。
明確な境界のない「佐賀」-サイクルと相互ロック。
締め切りはありません→「永遠の」サガとリソース漏れ。
オーケストレーターは、安定したストアなしで「メモリ内」状態を保存します。
テレメトリーセンターのない振付→「見えない」失敗。
不透明なUX:ユーザーは中間ステータスを表示しません。
17)クイックレシピ
SaaSクラシック:オーケストレーション+アウトボックス/受信トレイ、指数関数バックオフ、DLQ、サーガのステータスをUIで。
強い資源不変量:TCCとリザーブTTLとGCキャンセル。
大容量/負荷:イベント振り付け+厳格なidempotencyとキーメトリック。
マルチリージョン:ローカルサガ+最終集計;グローバルロックを避けてください。
おわりに
Sagasは、グローバルロックなしで分散システムで予測可能な一貫性を得る方法です。明確な補償、idempotence、信頼性の高い配信(outbox/inbox)、タイムアウトとリトレイの規律に加えて、テレメトリーとプレイブックは、負荷の増加、サービスと地域の数の増加に伴い、複雑なビジネスプロセスが安定して読みやすく維持されるようにするための鍵です。