イベント駆動ワークフローにおける冪等性の設計パターン:重複配送を前提とした実装
自動化ワークフロー

イベント駆動ワークフローにおける冪等性の設計パターン:重複配送を前提とした実装

要点 Kafka・SQS・Google Pub/Sub をはじめとする主要なメッセージブローカーは、実運用で at-least-once の配送保証を提供している。exactly-once は特定条件下でのみ達成可能で、汎用的な前提としては成立しない…

  • 5 分で読了
要点

Kafka・SQS・Google Pub/Sub をはじめとする主要なメッセージブローカーは、実運用で at-least-once の配送保証を提供している。exactly-once は特定条件下でのみ達成可能で、汎用的な前提としては成立しない。冪等性の設計は「実装時に必要になったら考える」問題ではなく、イベント駆動アーキテクチャを採用する時点で土台に組み込むべき前提である。本稿は 4 種の実装パターンとそれぞれのトレードオフを整理する。

なぜ exactly-once は保証されないのか

分散システムの現実として、メッセージブローカーとコンシューマーの間で「送った」「受け取った」「処理した」の 3 状態を、すべての障害シナリオを跨いで完全に同期させることはできない。ネットワーク切断、コンシューマーのクラッシュ、broker のリバランス——いずれの状況でも、確認 (ack) の欠落を安全側に倒すと重複配送が発生する。

Kafka の Transactional Producer と Idempotent Producer は、プロデューサ側の重複を抑制する仕組みだが、コンシューマ側の重複——処理途中でクラッシュしオフセットコミット前に再起動——を完全には防げない。Kafka の公式ドキュメントも「end-to-end exactly-once」の実現には Kafka Streams など特定パターンでの実装が必要と明記している。汎用的なユースケースでは、at-least-once を前提とした設計が現実解になる。

冪等性を実装する 4 パターン

実装アプローチには複数あり、それぞれ適用ドメインが異なる。

パターン 1: 冪等キー (Idempotency Key) 方式。プロデューサが一意な ID (UUID・request-id) をメッセージに付与し、コンシューマ側で「この ID を既に処理したか」を永続化ストアで照合する。処理済み ID の保持期間は、業務要件に応じて 24 時間から 1 週間程度が現実的である。金融取引・決済フローで最も多く採用される。

パターン 2: 業務状態の遷移チェック。処理結果が業務ドメインの状態遷移で表現できる場合——たとえば注文ステータスが「保留 → 承認 → 出荷」と単調に進む場合——現在の状態と期待する遷移が一致するかを条件付き更新で扱う。SQL の UPDATE ... WHERE status = 'pending' のように、期待状態を条件に含めることで、二重実行が自然に無効化される。

パターン 3: 上書き耐性のある操作。「顧客情報を最新値に更新する」「集計値を再計算する」といった、複数回実行しても最終結果が変わらない操作は、そもそも重複処理を無害化する構造を持つ。ただし、通知メール送信・請求書発行など副作用を伴う操作では、この方式は使えない。

パターン 4: 分散ロックによる直列化。冪等キー方式の変形で、リソース単位のロック (Redis の SETNX やデータベースの advisory lock) を用いて処理を直列化する。ロック取得失敗を「既に処理中」とみなして早期リターンする。もっとも、ロックの TTL 管理が難しく、複雑な業務フローには不向きである。

冪等キー方式の運用課題

実装頻度が高い冪等キー方式には、運用フェーズで顕在化する 3 つの課題がある。第 1 に、キー保存ストアの容量管理。毎秒 1,000 メッセージ規模のシステムでは、24 時間分だけでも約 86 M のキーが蓄積し、DynamoDB や PostgreSQL のインデックスコストが無視できない。TTL による自動削除の設計が必須になる。

第 2 に、キーの粒度設計。同じ業務エンティティに対する複数の操作を、1 つの ID で扱うか、操作ごとに別 ID を発行するか——これは業務仕様に強く依存し、後からの変更は極めて困難である。第 3 に、リプレイ時の挙動。障害時の一括再送や、テスト環境でのリプレイを、通常の重複と区別できるよう「リプレイフラグ」を設計に組み込む姿勢が実運用では有効である。

RPA・自動化プラットフォームでの適用

冪等性の議論は、伝統的なマイクロサービスだけでなく、RPA 大規模導入の保守コストが問題になる領域でも同じく重要である。RPA ロボットが同じ操作を二重実行すると、業務データの不整合や請求書の重複発行など、実害が発生する。イベント駆動での連携を導入する際に、冪等性の設計を初期から組み込む姿勢が、後の保守コストを大きく左右する。

また、生成 AI エージェント時代の RPAで扱う新しい世代の自動化プラットフォームは、非決定的な LLM 出力を含むため、冪等性の担保はさらに難しい。「同じ入力で同じ出力」が保証されないエージェントの実行結果を、業務システム側で「同じ操作かどうか」を判定する新しい設計層が必要になる可能性がある。

結論:設計時の判断の重み

冪等性は、後付けが最も難しい非機能要件の 1 つである。イベント駆動アーキテクチャを採用する時点で、どのパターンで冪等性を担保するかを設計文書に明記し、レビュー時にチーム全体が把握できる状態にすることが、運用フェーズでの負債を防ぐ最も現実的な方法である。Kubernetes 本番運用における etcd 分断の兆候と復旧手順で扱うインフラ障害からの復旧時にも、上位アプリケーション層の冪等性が確保されていれば、イベント再送処理の設計が大きく単純化される。

「動くようになってから考える」ではなく、「動く前から前提として扱う」——冪等性はこの姿勢を要求する数少ない設計論点である。

関連記事