Kafka Streams はトランザクションと状態ストアの仕組みにより、入力オフセット・内部状態・出力を書き込み単位で原子的にそろえることができます。これが Exactly-Once Semantics (EOS) です。
本稿では processing.guarantee の正しい選択と、アプリ・ブローカー・トピックの設定観点をまとめます。CCDAK(Confluent Certified Developer for Apache Kafka)で頻出の落とし穴も併記します。
Kafka Streams の EOS は、1 回の処理サイクルで以下を同一トランザクションに束ねることで、重複や不整合を避ける仕組みです。
1) 入力のコンシューマオフセット送信、2) 内部状態ストアの変更(RocksDB ⇄ changelog)、3) 出力トピックへのレコード書き込み。障害や再起動、リバランス時にも、これらが「全部反映される」か「全部取り消される」かのいずれかになります。
processing.guarantee はモードにより、重複発生の可能性やオフセットコミットの方法、状態ストア整合性が変わります。試験でも設定値と意味の取り違えが狙われます。
実務では、外部システムへ直接副作用を出さない限り exactly_once_v2 を基本選択とし、遅延・スループット要件から at_least_once へ切り替えるかを検討します。
| モード | 重複発生 | オフセットコミット | 状態ストア/出力の整合性 |
|---|---|---|---|
| at_least_once | あり(再処理で重複し得る) | 通常のグループコミット(トランザクション外) | 非原子的(部分適用の可能性) |
| exactly_once_v2 | なし(Kafka 内は重複防止) | SendOffsetsToTransaction によりTX内で送信 | 状態更新・出力・オフセットが原子的にコミット |
EOS v2 では、Streams スレッド単位のプロデューサを用い、出力トピックと内部 changelog、さらに入力オフセット送信を同一トランザクションに含めます。コミット時に全てが原子的に可視化され、アボート時には全てが無効化されます。
リバランスやクラッシュでスレッドが交代しても、プロデューサのフェンシングにより“ゾンビ”からのコミットをブロックし、一貫性を保ちます。
EOS v2 におけるトランザクション境界(概念図)
まずアプリで processing.guarantee=exactly_once_v2 を設定し、application.id は安定(再デプロイで不変)にします。内部トピックの耐障害性を確保するため replication.factor も指定します。
ブローカー側ではトランザクションログのレプリケーションと最小ISRを十分に確保します。トランザクションタイムアウトはブローカー上限内に収めます。
Kafka Streams(Java)設定例: Exactly-Once v2
Properties props = new Properties();
props.put(StreamsConfig.APPLICATION_ID_CONFIG, "orders-app");
props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "broker1:9092,broker2:9092");
// Exactly-Once v2 を明示
props.put(StreamsConfig.PROCESSING_GUARANTEE_CONFIG, StreamsConfig.EXACTLY_ONCE_V2);
// 内部トピックの耐障害性(StreamsConfig.TOPIC_PREFIX を利用)
props.put(StreamsConfig.TOPIC_PREFIX + "replication.factor", 3);
// トランザクション関連(producer.* で上書き可能)
props.put("producer.transaction.timeout.ms", 600000); // 10 分(broker 上限以下に)
// レイテンシ/スループット調整の一例
props.put("producer.linger.ms", 5);
props.put("producer.batch.size", 32768);
// コミット間隔(EOS では短めでも一貫性は保たれる)
props.put(StreamsConfig.COMMIT_INTERVAL_MS_CONFIG, 100);
// スレッド並列度
props.put(StreamsConfig.NUM_STREAM_THREADS_CONFIG, 2);
StreamsBuilder builder = new StreamsBuilder();
KStream<String, String> orders = builder.stream("orders");
KTable<String, Long> counts = orders.groupByKey().count();
counts.toStream().to("orders-agg");
KafkaStreams streams = new KafkaStreams(builder.build(), props);
streams.start();グレースフルシャットダウン時は、現在のトランザクションをコミット/アボートしてから停止する必要があります。SIGTERM ハンドリングや close(Duration) を利用してください。
リバランスではタスクの移動前にトランザクションが片付くまで待機が発生します。スレッド数や入力分割を見直してトランザクション時間を短く保つと安定します。
processing.guarantee=exactly_once_v2 を選ぶと、入力オフセット送信・内部状態更新・出力が同一トランザクションで原子的にコミットされます。外部システムは含まれません。
Streams では transactional.id を自前で付けないのが通常です(内部で生成・管理)。application.id は安定させるのが鉄則です。
CCDAK
問題 1
Kafka Streams アプリで注文を集計し、結果を単一の出力トピックへ書き込みます。再起動やリバランス時にも、内部状態更新・出力・入力オフセットを原子的にコミットし、Kafka 内での重複を避けたい。正しい設定と前提の組み合わせはどれか?
正解: A
Exactly-Once を有効化するには Streams 側で processing.guarantee=exactly_once_v2 を設定し、application.id を安定させます。ブローカーはトランザクションログ(transaction.state.log.*)の十分なレプリケーション/ISR が必要です。B は Streams の文脈を無視、C は重複防止と無関係、D はアプリケーション整合性を保証しません。
exactly_once_v2 は常にデフォルトですか?
いいえ。多くのバージョンでデフォルトは at_least_once です。Exactly-Once を前提に設計するなら processing.guarantee=exactly_once_v2 を明示してください。
EOS で外部データベースへの書き込みも原子的にできますか?
できません。EOS は Kafka 内の出力・内部トピック・入力オフセットに限定されます。外部DBに対しては二相コミット、アウトボックス、または外部側の一意制約/冪等APIなどを併用します。
トランザクションがタイムアウトした場合はどうなりますか?
トランザクションはアボートされ、そのバッチ内の出力・changelog・オフセット送信は可視化されません。処理は再試行されます。transaction.timeout.ms を適切に設定し、処理時間を短く保つ設計が有効です。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Kafka Topic と Partition の基礎: 分散とスケーラビリティの要
CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...
CCDAK 試験ガイド:出題範囲・配点・申込み・対策
Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...
Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点
CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...
Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性
レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...
Kafka の Offset とコミット: ポジション管理と at-least-once の基礎
CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...