Kafkaのパーティションログ、offset、保持とconsumer commit

Apache Kafkaのtopicは複数のpartitionに分かれ、各partitionが順序付きログになります。順序が定義されるのはpartition内であり、partitionをまたぐ全体順序はありません。keyは同じkeyのレコードを同じpartitionへ送るためによく使われますが、partition数やpartitionerを変えると配置の前提が変わる場合があります。offsetはpartitionログ上の位置です。retentionやcompactionで該当レコードが消えることがあるため、現在保持されているレコードの永久IDではなく、消費位置として理解します。

実務家の視点:Kafkaは読み取り後に消えるqueueとは異なる

Kafkaの初期開発者でConfluent共同創業者のJay Krepsは、Kafkaを保持ログとして使う設計を論じ、再生、event sourcing、ディスク保存、複製の用途を説明しています。これは開発者かつベンダー経営者のアーキテクチャ上の見解です。任意の環境で永久保存される保証ではありません。保持期間は時間・容量ベースのcleanup、compaction、複製、ディスク容量、運用設定に依存します。compactionはkeyごとの一部の最新値を非同期に残す仕組みで、全履歴のarchiveではありません。tombstoneも設定したdelete-retention期間後に削除され得ます。

耐久性はproducerとbrokerの設定条件に依存

どの設定・障害でもレコードが無損失で処理されるという一般保証はありません。producerのacknowledgementとretry、replication factor、同期中replicaの最小数、leader選出、ストレージの挙動が失敗時の範囲を決めます。acks=0、leader応答、設定済み同期replicaの応答はそれぞれ意味が異なります。成功応答が何を確認したのかを運用文書に明記します。consumerが処理前にoffsetをcommitすると障害時に処理漏れが起き得ます。処理後のcommitでは再処理が起きる可能性があります。どちらも外部副作用のexactly-onceを自動で保証しません。

並列性、順序、再生の範囲

consumer groupでは通常partitionをmemberへ割り当て、partition単位で並列化します。consumer数がpartition数を超えても、そのgroup内で割り当てられるpartitionは増えません。worker poolを使いながら順序を保つには、完了状況を追跡し、安全な次の位置だけcommitする必要があります。再生できるのは必要なレコードが保持されている間です。対応する処理方式ではKafka transactionによりKafka内の入力offsetと出力recordを原子的に扱えますが、外部DBや決済処理まで自動で含むものではありません。保持期間、複製ack、commit方式、lag・disk監視、再生手順を併せて設計してください。

参考資料