要点: ブローカーが順序を保証する範囲は限定的です。業務側が、何を同じ順序で扱うか決める必要があります。
この記事の用語: 順序制御:イベント順序。重複排除:重複排除。再実行:履歴イベントを再実行すること。
現場の課題
全体順序は並列性を失わせます。再試行は重複を生み、遅れて届いたイベントは新しい状態を上書きします。履歴再実行でメールや決済を再送する危険もあります。
単純な対策だけでは不十分な理由
順序保証はパーティションなど限定範囲です。業務オブジェクトごとに必要な順序を決め、コンシューマーはバージョン、重複排除、外部作用の分離で遅延イベントと再実行へ備えます。
処理フロー
業務上の集約 バージョン→パーティション
キー別Order→コンシューマー
受信済みテーブル・バージョン→再実行
副作用隔離
アーキテクチャ上の判断
業務上の集約 バージョン
Duplicate、Gap、Staleを検出します。
Gapを局所隔離
他キーを止めずParkします。
再実行-safe コンシューマー
プロジェクトionと通知等を分離します。
さらに深く考える
Exactly-onceはOutcome
外部システムにはBusiness 冪等性が必要です。
Meaningもバージョン化
旧Fixtureを新コンシューマーでテストします。
実装手順
- 順序を守る業務範囲と一致するパーティションキーを選びます。
- イベントID、オブジェクトID、オブジェクトバージョン、発生時刻をすべてのイベントへ含めます。
- 履歴再構築と、メール・決済などの外部作用を分離します。
コード例: バージョン-aware コンシューマー
if inbox.contains(event.id): ACK
current = projection.version(event.aggregateId)
if event.version <= current: ACK
if event.version > current + 1: park(event)
transaction(apply(event), inbox.add(event.id))
ACKParkしたGapにはアラートと復旧 ポリシーが必要です。
想定しておく障害
- マイグレーションでバージョンがResetします。
- 再実行が通知を再送します。
- Hot 業務上の集約がパーティションを飽和させます。
監視すべきこと
| 指標 | 何が分かるか |
|---|---|
| Gap・Stale率 | 順序制御不具合です。 |
| 重複排除 ヒット率 | Delivery不安定を示します。 |
| 再実行 Throughput | 復旧進捗です。 |
設計の検証方法
- イベントをShuffle・Duplicate・Delayします。
- 隔離プロジェクトionへ履歴再実行します。
- Hot パーティション時の他キーを確認します。
本番導入の進め方
イベントID、オブジェクトバージョン、観測メトリクスを先に追加します。一コンシューマーへ受信済みテーブル 重複排除を導入し、再実行専用環境で全履歴を訓練してから障害対応で使います。
本番前チェックリスト
- Stream別順序制御を文書化します。
- Duplicate・Delayを許容します。
- 再実行にRateとSide-effect ポリシーがあります。
まとめ
イベント処理の正しさは、明確な順序保証の範囲と決定的なコンシューマーから生まれます。
