アーキテクチャパターン

アウトボックスパターン あうとぼっくすぱたーん

トランザクショナルアウトボックスメッセージング結果整合性マイクロサービスイベント駆動二重書き込み問題
アウトボックスパターンについて教えて

簡単に言うとこんな感じ!

「DBを更新したのにメッセージ送信が失敗して、データがバラバラ…」という事故を防ぐ仕組みだよ! 更新内容を一旦「送信待ちトレイ(アウトボックス)」にまとめて保存しておいて、あとでまとめて送り出すってこと!


アウトボックスパターンとは

アウトボックスパターン(Transactional Outbox Pattern)とは、データベースの更新とメッセージの送信を確実に一致させるためのアーキテクチャパターンです。システムがデータを保存すると同時に外部へ通知(メッセージ)を送る必要がある場面で、「保存は成功したのに通知が届かなかった」「通知は飛んだのにDBが更新されていなかった」といった矛盾(不整合)を防ぎます。

マイクロサービス構成やイベント駆動アーキテクチャでは、複数のシステムがメッセージキューイベントバスを介して連携します。このとき「DBへの書き込み」と「メッセージの送信」を別々に行うと、どちらか一方が失敗するリスクがあります。これを二重書き込み問題(Dual Write Problem)と呼びます。アウトボックスパターンはこの問題を解決するための標準的な手法として広く採用されています。

具体的には、「送るべきメッセージ」をいったんアプリケーションと同じデータベースの専用テーブル(アウトボックステーブル)に書き込み、別のプロセスがそれを読み取って実際にメッセージを配信します。DBへの書き込みとアウトボックステーブルへの書き込みを同一トランザクション内で行うことで、両者の整合性が保証されます。


アウトボックスパターンの仕組み

処理の流れ

ステップ実行内容ポイント
① アプリが更新業務データを更新し、同一DBのアウトボックステーブルにメッセージを書き込む同一トランザクションで実施
② コミットトランザクションが成功すれば両方が確実に保存される失敗すれば両方ロールバック
③ 配信プロセスが読取アウトボックステーブルを監視し、未送信メッセージを取得別プロセス・非同期で動作
④ メッセージを送信メッセージキュー(Kafkaなど)や他サービスへ配信失敗しても再試行可能
⑤ 送信済みマーク送信が完了したレコードを削除 or ステータス更新冪等性に注意

配信プロセスの実現方法

配信プロセス(アウトボックスを読んで送り出す役割)には主に2種類のアプローチがあります。

  • ポーリング方式:定期的にアウトボックステーブルをSELECTして未送信メッセージを取得する。実装がシンプルで導入しやすい。
  • CDCベース方式CDC(Change Data Capture)と呼ばれる技術でDBのログ(WAL)を監視し、変更をリアルタイムに検知する。Debezium などのOSSが代表例。

覚え方

手紙は一旦アウトボックスに入れてから郵便屋さんに渡す」と覚えよう! 書いた手紙(メッセージ)を直接ポスト(キュー)に投げ込むのではなく、デスクのトレイ(アウトボックス)にしまってから、郵便屋さん(配信プロセス)が後でまとめて持っていく。書いた瞬間に消えても、トレイに入っていれば再配達できる!


歴史と背景

  • 2000年代〜SOA(サービス指向アーキテクチャ)の普及とともに、サービス間のデータ整合性問題が顕在化。分散トランザクション(2PC)が主流だったが、性能・可用性の課題が大きかった
  • 2010年代前半マイクロサービスアーキテクチャの概念が広まり、各サービスが独立したDBを持つ設計(Database per Service パターン)が一般化。これにより二重書き込み問題が急増
  • 2015年頃:Chris Richardsonがマイクロサービスパターンを体系化し、Transactional Outbox Patternとして広く紹介。microservices.io で公式パターンとして掲載
  • 2017年〜:KafkaやRabbitMQなどのメッセージブローカーが普及し、アウトボックスパターンとの組み合わせが定番化
  • 2019年〜:DebeziumなどのCDCツールが成熟し、ポーリングに代わるCDCベースの実装が主流になりつつある
  • 現在クラウドネイティブ・マイクロサービス設計の必須パターンとして、AWS・Azure・GCPのリファレンスアーキテクチャにも登場

関連する技術・パターンとの比較

アウトボックスパターン vs 他の整合性確保手法

手法概要メリットデメリット
アウトボックスパターンDB更新と同一トランザクションでメッセージを一時保存確実な整合性・実装がシンプルアウトボックステーブルの管理が必要
2フェーズコミット(2PC)複数DBを一括でコミット強整合性性能劣化・可用性低下のリスク大
SAGAパターン分散トランザクションを補償トランザクションで対処サービス独立性を保てるロールバックロジックが複雑
直接メッセージ送信DB更新後に即座にキューへ送信実装が最もシンプル二重書き込み問題が発生しうる

アウトボックスパターンの構造(SVG図解)

アプリケーション 注文を処理する (例: 注文サービス) 同一トランザクション 業務テーブル orders, users ... など (通常のDB更新) アウトボックステーブル id / event_type / payload status: PENDING → SENT 配信プロセス ポーリング or CDC(Debezium) メッセージキュー Kafka / RabbitMQ ※ 業務テーブルとアウトボックステーブルへの書き込みは同一DBトランザクション内で実施

冪等性への対応

配信プロセスは失敗時に再試行するため、同じメッセージが複数回送られる可能性があります。受け取り側が冪等(べきとう)—何度受け取っても同じ結果になる—設計であることが重要です。実務では、メッセージIDで重複チェックを行うのが一般的です。


関連用語

  • マイクロサービス — アプリを小さな独立したサービスに分割するアーキテクチャスタイル
  • SAGAパターン — 分散トランザクションを補償処理で実現するパターン
  • イベント駆動アーキテクチャ — イベントの発生を起点にシステムを連携させる設計手法
  • メッセージキュー — サービス間でメッセージを非同期に受け渡す仕組み
  • CDC(Change Data Capture) — DBのログを監視してデータ変更をリアルタイム検知する技術
  • 結果整合性 — 即時ではなく最終的にデータが一致することを保証する考え方
  • トランザクション — 複数の処理をひとまとまりとして扱い、全部成功か全部失敗かを保証する仕組み
  • Debezium — OSSのCDCプラットフォーム。アウトボックスパターンの配信プロセス実装によく使われる