Kafkaの再送は可用性を高めますが、そのままだとブローカ再試行で重複書き込みが起こります。Idempotent Producerは、プロデューサ側だけで「同一パーティション内での重複なし」を実現する定番機能です。
本稿では、enable.idempotenceの内部動作、必須/推奨設定、障害シナリオ、運用と試験対策をまとめます。バージョン差異で揺れやすい点は慎重に表現しています。詳細はKafkaおよびConfluentの公式ドキュメントの記載に従ってください。
プロデューサはネットワーク断やリーダー交代で送信失敗を検出すると再送します。通常の再送だけでは、同一レコードが同一パーティションに二重書き込みされることがあります。これをアプリケーション側で除外するのは負担が大きく、特にキューイングや決済系では致命的です。
Idempotent Producerは、プロデューサIDとシーケンス番号により、ブローカでの重複受理を防ぎます。これにより、再送を前提としつつ、同一パーティション内での挿入を一意に保てます。CCDAKでは「必要な設定の組み合わせ」「どこまで保証できるか(範囲)」の理解が頻出です。
Idempotent Producerは、ブローカから割り当てられるProducerId(PID)と、パーティションごとの単調増加シーケンス番号で各レコードバッチを識別します。ブローカ(リーダー)は受信したPIDとシーケンス番号を保持し、既知の組み合わせは重複として破棄し、正しい順序のみを受け付けます。
acks=allにより、ISR全体でのレプリカ反映を待ってから成功応答するため、ネットワーク断やリーダー交代でも同一レコードの二重可視化を抑制できます。プロデューサはOutOfOrderSequenceやUnknownProducerIdなどのエラーに対して自動リカバリを行い、必要に応じてエポックを更新して再初期化します。
Idempotent Producerの重複排除フロー(概念)
Idempotent Producerを有効化するには、enable.idempotence=trueが中核です。これに整合するため、acks=all、retries>0(多くの実装では実質的に大値)、max.in.flight.requests.per.connectionは制約内(一般に5以下)とする必要があります。クライアント実装により、矛盾する設定はエラーにしたり、自動的に上書き・制限する場合があります。試験では要件関係を問われやすいです。
delivery.timeout.msは全リトライの上限時間です。これを超えると送信は失敗として扱われますが、途中の再送での重複はIdempotent Producerが防ぎます。スループット最適化にはlinger.msやbatch.sizeを併用するとよいですが、遅延許容と相談してください。Confluent Cloudなどマネージド環境ではacks=allが前提のことが多く、Idempotent Producerは通常サポートされます。
注意: 既定値や自動調整の挙動はクライアントとバージョンに依存する場合があります。最新の公式ドキュメントを確認してください。
| 配信保証モード | 主な設定 | 重複発生 | 順序性 |
|---|---|---|---|
| At-most-once | acks=0 または acks=1, retries=0 | 発生しないが欠落の恐れ大 | 保証弱い |
| At-least-once | acks>=1, retries>0, enable.idempotence=false | 発生し得る(再送で二重) | max.in.flight=1で強化可 |
| Idempotent | enable.idempotence=true, acks=all, retries>0, max.in.flight<=5 | 同一パーティション内で防止 | 強い(パーティション単位) |
| Transactional EOS | Idempotentに加えtransactional.id設定、適切な消費隔離 | 読み書き一貫で防止(複数パーティション横断可) | 強い(トランザクション境界) |
Java Producerの最小設定例(冪等+スループット配慮)
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "broker:9092");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
// 冪等化の中核
props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");
props.put(ProducerConfig.ACKS_CONFIG, "all");
props.put(ProducerConfig.RETRIES_CONFIG, Integer.toString(Integer.MAX_VALUE));
props.put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, "5"); // 順序と整合性
// スループットと安定性
props.put(ProducerConfig.LINGER_MS_CONFIG, "20");
props.put(ProducerConfig.BATCH_SIZE_CONFIG, "65536");
props.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, "120000");
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
ProducerRecord<String, String> rec = new ProducerRecord<>("orders", "order-123", "payload");
producer.send(rec, (md, ex) -> {
if (ex != null) {
// 失敗時の補足ロギング。冪等化により重複は防がれる
ex.printStackTrace();
}
});
producer.flush();
producer.close();ネットワーク断、リーダー交代、ログ切り詰めなどで、プロデューサとブローカ間の状態がずれることがあります。Idempotent Producerはエポック管理とシーケンス制御で回復を試みますが、アプリ側でのリトライ設計と監視が重要です。
代表的なエラーと挙動は次の通りです。詳細な発生条件はブローカとクライアントのバージョン、設定に依存するため、運用環境に合わせてテストしてください。
冪等化の有効・無効は設定で明確ですが、実運用では再送率、スロットリング、レイテンシの傾向を継続監視します。プロデューサメトリクス(record-error-rate, record-retry-rate, request-latency-avg, produce-throttle-time-avg, batch-size-avg, records-per-request-avgなど)をダッシュボード化し、delivery.timeout.ms到達のエラー数と合わせて確認しましょう。
スループット最適化は、linger.msとbatch.sizeでバッチングを強化しつつ、max.in.flight<=5の制約下で並列度を確保するのが基本線です。キーの設計は重要で、同一キーを同一パーティションへ安定的にルーティングすることで、アプリケーション上の整合性も保ちやすくなります。
マネージド環境(例: Confluent Cloud)では、acks=allが前提・推奨であり、Idempotent Producerは標準的に利用可能です。クライアント側の既定値や制約は随時更新され得るため、導入時に該当環境のドキュメントを確認してください。
試験では、Idempotent Producerの保証範囲と必須設定の組み合わせ、トランザクションとの違いが問われがちです。単なるretries増加は重複を防がないこと、acks=allの意味、max.in.flightの制約を整理しておきましょう。
また、Idempotent Producerは「書き込み側の重複防止」であり、消費側の重複読取りとは別問題です。エンドツーエンドのExactly-Onceを目指すケースでは、トランザクションやKafka StreamsのEOSモードを使うことを区別して答えられるようにします。
CCDAK
問題 1
Kafkaプロデューサで再送時の重複を同一パーティション内で防止したい。どの設定の組み合わせが要件を満たすか?
正解: A
Idempotent Producerはenable.idempotence=trueが前提で、acks=allと整合する必要があります。順序性と整合性の観点からmax.in.flight.requests.per.connectionは制約内(一般に5以下)。Bは冪等化なしで重複が起こり得ます。Cはacks=1で整合しません。Dはトランザクションでも内部的に冪等化が基盤であり、単独では要件を満たしません。
enable.idempotenceは既定で有効ですか?
多くのKafkaクライアントでは既定はfalseです。重複防止を要件とする場合は明示的にtrueに設定し、acks=allなど関連設定の整合を取ってください。クライアントやバージョンで既定値が変わる可能性があるため、導入時に公式ドキュメントを確認してください。
Idempotent Producerでコンシューマ側の重複読取りも防げますか?
いいえ。Idempotent Producerは書き込み時の重複受理を防ぐ機能です。消費側の重複はオフセットコミット戦略やトランザクション(read_committed)などで扱います。エンドツーエンドのExactly-Onceが必要なら、トランザクションやKafka StreamsのEOSを検討してください。
max.in.flight.requests.per.connectionは1に固定すべきですか?
冪等化のないAt-least-onceで厳密な順序を守る目的なら1が選ばれることがありますが、Idempotent Producerでは一般に5以下で順序と整合性を保てます。1はスループット低下が大きいため、要件に応じて1〜5で調整してください。
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-...