動機
「DBへの書き込み」と「キューへ挿入」をアトミックに行いたい。
これを実現可能な方法には、CDC と Outbox Pattern がある。
CDC (Change Data Capture) とは
CDCコネクターがDBにレプリケーション権限で接続し、DB のトランザクションログ(MySQLのBinlog、PostgreSQLのWALなど)をそのまま取得する。こうして得られた変更操作 (挿入(Insert/Update/Delete) をメッセージブローカーに配信する。
Transactional Outbox Pattern とは
クライアントがデータ更新時に、「データ更新」と「更新内容を Outboxテーブルへの保存」をトランザクション内で行う。別のプロセス (無限ポーリンジグジョブやCDCコネクター)がこれを読み取り、これをメッセージブローカーに配信して、Outboxテーブル内のレコードを削除(物理/論理)する。メッセージの配信は、At-least-once である。
両者の比較
正直強力な決め手はないため、面接ではデフォルトでCDCを使う。
CDCの長所は、
- アプリケーションのコード修正が不要であり、業務ロジックとイベント配信ロジックを完全に分離できる。
- DBのトランザクションログを直接利用するため、イベントの欠損リスクが極めて低く、データの信頼性が非常に高い。
- DBへの追加の書き込みが発生しないため、DBへの負荷が問題にならない。
- リアルタイム性が極めて高いため、分析基盤や外部サービスとの同期を低遅延で実現できる。(Outbox Pattern だと、ポーリング頻度に依存する)
- 将来的な拡張性が高く、一度設定すれば後から別のコンシューマーを追加するのも容易である。
Outbox Patternの長所は、
- 外部依存ツールが不要で、標準的なRDBMSのテーブル操作だけで完結するため、導入のハードルが非常に低い。
- 特定のDB製品に依存しないため、CDCコネクターが対応していないデータベースや、マネージドサービス等の制約がある環境でも実現可能である。
- イベントの制御がアプリケーション側で完結するため、複雑な変換ロジックや特定の条件でのみイベントを発行する等の細かい制御がしやすい。
- 学習コストと運用負荷が低いため、小規模なプロジェクトや、インフラ構成をシンプルに保ちたい場合に最適である。
- アプリケーション側で
OrderCreatedのような意味のあるビジネスイベントを直接定義できるため、DBの行更新をそのまま通知するCDCよりも意図が明確になる。