【イグザクトリーワンスはいしん】

Exactly Once配信 とは?

最終更新:
💡 重複も欠落もなく「ちょうど1回」を届ける、範囲限定の特急便

メッセージキューやストリーム処理で、1件のメッセージの結果が重複も欠落もなく「ちょうど1回」だけ反映されるようにする配信保証。保証される範囲と条件は製品ごとに決まっていて、外部システムへの書き込みまで含めるには受け側の工夫も必要になる。

📌 このページのポイント
Exactly Once配信:厳密に1回だけ届く 配信セマンティクスの比較 At Most Once 0回または1回 消失あり・重複なし ⚠ 失う可能性 At Least Once 1回以上 消失なし・重複あり ⚠ 重複の可能性 Exactly Once 厳密に1回 消失なし・重複なし ✓ 最も強い保証 Exactly Onceの実現(Kafka内の読み書きの例) べき等な送信 (ID+連番) + トランザクション (Atomic書き込み) = Exactly Once 実現
Exactly Once配信:3段階の配信保証の比較と実現方法(Kafka外への書き込みは受け側の対策が必要)
ひよこ ひよこ
Exactly Once配信って、ぴったり1回だけ届くってこと?
ペンギン先生 ペンギン先生
そうだよ。重複もしないし、消えもしない、ちょうど1回だけ結果に反映されることを保証する方式なんだ。ただ、どこからどこまでを「1回」にするかは製品ごとに決まっていて、その範囲の中での約束だよ
ひよこ ひよこ
それって難しいの?
ペンギン先生 ペンギン先生
かなり難しいんだよ。送った側が返事を受け取れなかったとき、「届いたけど返事が消えた」のか「そもそも届いていない」のか区別できないからね。再送すれば重複が起きうるし、再送しなければ欠落が起きうる。Kafkaも初期設定の保証はAt Least Once(重複の可能性あり)なんだ
ひよこ ひよこ
どうやって実現するの?
ペンギン先生 ペンギン先生
Kafkaでは、ブローカーがプロデューサーごとにIDを割り当てて、メッセージに付いた連番で再送による重複を捨てる「べき等プロデューサー」があるよ。さらにトランザクションを使うと、複数のパーティションへの書き込みと「どこまで読んだか(オフセット)」の記録をまとめて確定できる。これでKafkaからKafkaへの読み取り→処理→書き込みをExactly Onceにできるんだ
ひよこ ひよこ
じゃあKafkaを使えば送金処理も安心?
ペンギン先生 ペンギン先生
そこは注意が必要だよ。Kafkaの外にあるDBへの書き込みやメール送信は、Kafkaのトランザクションには含まれないんだ。公式ドキュメントでも、外部に出力するなら出力結果と読み取り位置を同じ場所に保存する方法が紹介されているよ。送金IDで二重実行を防ぐような、べき等な処理を受け側で用意するのが定番だね
ひよこ ひよこ
他のサービスにもExactly Onceってあるの?
ペンギン先生 ペンギン先生
Google CloudのPub/SubにもExactly Once配信があるけど、対象はpullサブスクリプションだけで、同じリージョンから接続する場合に限られるよ。確認応答に成功したメッセージは再配信されない一方、通常より配信の遅延がかなり大きくなると説明されているんだ。保証の範囲と引き換えのコストを確認してから選ぼうね
もっと詳しく知りたい人へ

Exactly Onceが使えない場面では、どうやって重複を防ぐ?

At Least Onceで受け取り、受け側の処理をべき等にするのが一般的だよ。たとえば注文IDや送金IDをDBの一意キーとして保存し、同じIDが2回来たら処理済みとしてスキップする。Kafkaの公式ドキュメントでも、外部システムへ出力する場合は、出力結果と読み取り位置(オフセット)を同じ場所に保存する方法が紹介されているよ。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「Exactly Once」って出てきたら「決められた範囲の中で、重複も欠落もなく1回だけ反映する配信保証」と思えればだいたいOK!
📖 おまけ:英語の意味
「Exactly Once Delivery」 = ちょうど1回の配信
💬 「正確に(exactly)1回(once)」届けるという意味だよ。実際の製品では、ネットワークの再送そのものをなくすというより、重複を見つけて捨てたり、書き込みと読み取り位置の記録をまとめて確定したりして「結果として1回」にする仕組みが多いんだ

参考資料

← 用語集にもどる