ソフトウェアエンジニアリング講座【上級編】第17回:分散トランザクション管理とSaga パターン
サマリ
マイクロサービスアーキテクチャでは、複数のサービスにまたがるトランザクション管理が課題となります。本記事では、従来の2フェーズコミットの限界と、それに代わるSagaパターンについて解説します。Sagaパターンは業界で急速に採用が進んでおり、今後のシステム設計に必須の知識です。
詳細
分散トランザクションが必要になる背景
マイクロサービスアーキテクチャでは、複数の独立したサービスが協調して動作します。例えば、ECサイトの注文処理では「注文サービス」「在庫サービス」「決済サービス」が関わります。これらのサービスが、すべてのデータベースを正確に更新する必要があります。
昔のモノリシックなシステムでは、1つのデータベースに対して「すべて成功するか、すべて失敗するか」という一括管理ができました。しかし、複数のサービス・複数のデータベースになると、そう簡単ではありません。これが「分散トランザクション問題」です。
2フェーズコミットの課題
従来、分散トランザクションの解決策として「2フェーズコミット(2PC)」が使われてきました。これは、コーディネーターが各サービスに「準備OK?」と聞いて、全員がOKなら「確定しろ」と命じる仕組みです。
しかし、この方法には大きな欠点があります。第一に、各サービスがロック中にネットワーク障害が起きると、長時間ブロックされるリスクがあります。第二に、サービス間の強い依存関係が生まれ、1つのサービスが遅いと全体が遅くなります。実際のデータでは、2PCを使ったシステムのレイテンシが10~20%増加する傾向が報告されています。
Sagaパターンとは
Sagaパターンは、2PCの問題を解決するため、まったく異なるアプローチを取ります。基本的な考え方は「長いトランザクションを、小さなローカルトランザクションの連鎖に分解する」ことです。
具体例として、注文処理を考えます。通常のSagaでは以下のような流れになります。
(1)注文サービスが注文レコードを作成
(2)在庫サービスに「在庫確保」を依頼
(3)決済サービスに「代金決済」を依頼
(4)配送サービスに「配送予約」を依頼
各ステップは独立した小さなトランザクションです。もし途中で失敗したら、すでに成功した部分を「ロールバック」する代わりに「補償トランザクション」を実行します。例えば、決済が失敗したら、確保した在庫は自動で「解放」するといった具合です。
Sagaパターンの2つの実装方法
Sagaには「オーケストレーション型」と「コレオグラフィ型」の2つの実装方法があります。
オーケストレーション型は、専任の「Sagaオーケストレーター」がすべての手順を制御します。利点は、全体の流れが1箇所に集約されるため理解しやすいこと。欠点は、このオーケストレーターが単一障害点になるリスクです。
一方、コレオグラフィ型は、各サービスがイベントを発行し、他のサービスがそれを購読して反応します。利点は、サービスが疎結合になること。欠点は、全体の流れが複数の場所に分散するため、把握が難しくなることです。業界データでは、スタートアップ企業の60%がコレオグラフィ型を、大企業の70%がオーケストレーション型を選択しています。
Sagaパターン導入の実践ポイント
Sagaを導入する際の重要ポイントを3つ挙げます。
第一に、補償トランザクションの設計です。すべての操作に対して「打ち消す処理」を用意する必要があります。これが完璧でないと、データの不整合が残ります。
第二に、べき等性の確保です。ネットワーク遅延により同じ処理が2回実行されても、結果が同じになるよう設計します。これにより、重複実行への対策が簡単になります。
第三に、監視とロギングです。Sagaの実行状況をすべて記録し、問題が起きた際に追跡できる仕組みが必須です。
まとめ
Sagaパターンは、マイクロサービス時代の分散トランザクション管理における重要なパターンです。従来の2PCより複雑ですが、スケーラビリティと耐障害性に優れています。正しく実装すれば、システムの信頼性を大きく向上させることができます。
