Kafka Producerはレコードをパーティション単位でバッチ化して送信します。batch.sizeは1バッチの最大バイト数、linger.msは満杯でない場合に追加レコードを待つ上限時間です。
本稿は公式ドキュメントの安定動作に基づき、スループットと遅延SLAのバランスを取るための具体的な指針を示します。CCDAK向けの要点整理と、現場で迷いがちな落とし穴もカバーします。
batch.sizeはパーティションごとの1送信バッチの最大サイズ(バイト)です。実際のバッチサイズは直近に蓄積できたデータ量で決まり、上限としてbatch.sizeが効きます。多数の小レコードでネットワーク効率を上げたい場合や圧縮効率を上げたい場合に増やします。
linger.msは、バッチが満杯でないときに追加のレコードを待つ最大時間(ミリ秒)です。満杯になれば待たずに送信されます。よって、トラフィックが低い時間帯でもある程度まとめて送ることができますが、その分だけ待機遅延が増えます。デフォルトは一般に0msで、待ち時間を持たず即時寄りに送信します。
重要な前提として、バッチはパーティション単位で形成されます。多パーティションに一様に書き込む場合、同時に複数の未送信バッチが存在しうるため、batch.sizeの設定はbuffer.memoryの消費にも影響します。
| プロファイル | batch.size(目安) | linger.ms(目安) | 特徴 |
|---|---|---|---|
| 低遅延 | 16〜32KB | 0〜2ms | 最小の送信待機。小バッチ多発でネットワーク効率はやや低い |
| バランス | 32〜64KB | 5〜15ms | 圧縮効率と遅延のバランスが良い汎用設定 |
| 高スループット | 64〜128KB+ | 20〜50ms | 大きなバッチでネットワーク/圧縮効率最大化。P99遅延は増える |
Producerはスレッド内でRecordAccumulatorにレコードを蓄積し、パーティションごとにバッチを形成します。送信は2つの条件で起こります。1つはバッチがbatch.sizeに達したとき、もう1つはlinger.msの待機上限に到達したときです。どちらか早い方がトリガになります。
Senderスレッドは蓄積済みバッチをまとめてネットワーク送信します。acks、retries、max.in.flight.requests.per.connectionなどの設定は、スループットや再送時のふるまい(および順序保証)に影響します。圧縮はバッチ単位で行われるため、ある程度のバッチサイズとlinger.msを与えることは圧縮効率を高め、帯域利用を抑制します。
近年のKafkaではバッチ効率を高めるためにパーティショニング戦略が改善されていますが、本質は「パーティション単位の蓄積と、サイズ・時間の二重条件での送信」です。このメカニズム自体はバージョンに依存せず安定しています。
Producerのバッチ形成と送信の概念図
エンドツーエンド遅延SLA(例: P99 ≤ 200ms)から逆算し、プロデューサ側で許容できる送信待機時間を決めます。linger.msは最悪ケースでそのまま待機遅延に加算されうるため、ネットワークとブローカー応答(acks)にかかる平均/分位数レイテンシを差し引いて上限を設定します。
たとえば、ブローカー往復(acks=all)のP99が80ms、アプリ処理が50msなら、プロデューサ側で許せる待機は概ね70ms以内です。ただし、レコード到着間隔が疎なときはlinger.msに達してから送信されることが多くなるため、平均遅延を押し上げます。SLAが厳しい場合は小さめに、到着レートが高い場合はサイズトリガが先に効くのでlinger.msをやや大きくしても実遅延影響は限定的です。
大きなbatch.sizeは、同時に未送信のパーティション数が多いとbuffer.memoryの消費を増やします。送信待ちがかさむとproduce()がmax.block.msまでブロックし、アプリ側のスループットに影響します。観測しながら段階的に増やし、必要ならパーティション数や送信並列の設計も見直しましょう。
再送(retries)や高いmax.in.flight.requests.per.connectionはスループットに効きますが、順序性や重複の扱いは設定に依存します。実運用ではenable.idempotence=trueとacks=allの併用を基本とし、必要に応じてmax.in.flightの上限を調整します。公式実装では、イドポテンス有効時に重複排除と順序保証が強化されます。
前提として、ステージングまたは隔離可能なトピックで検証します。指標は平均だけでなくP95/P99を見ます。ネットワークとブローカー側の負荷も併せて監視します。
手順: 1) 現状計測(record-send-rate、request-latency-avg、batch-size-avg、compression-rate-avg、retriesなど)。2) compression.typeをlz4またはzstdへ。3) batch.sizeを段階的に32KB→64KB→128KBと引き上げ、同時にlinger.msを0→5→10→20msの順で上げて比較。4) P99遅延が許容超過ならlinger.msを戻す。5) メモリ圧迫が見えたらbatch.sizeを一段戻し、送信平準化やパーティション戦略を見直す。6) 本番導入時はローリングで適用し、ブローカー負荷を監視。
CLIのkafka-producer-perf-testや、アプリ内でワークロード相当のメッセージサイズ分布を再現して測ると、設定の効果が読み取りやすくなります。
プロデューサ設定例(Java Properties)
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka-1:9092,kafka-2:9092");
props.put(ProducerConfig.ACKS_CONFIG, "all");
props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");
props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "lz4");
// バッチと待機のチューニング(例: バランス型)
props.put(ProducerConfig.BATCH_SIZE_CONFIG, 65536); // 64KB
props.put(ProducerConfig.LINGER_MS_CONFIG, 10); // 10ms
// タイムアウトと再送の整合性
props.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 120000); // 総配信上限
props.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000);
props.put(ProducerConfig.RETRIES_CONFIG, Integer.toString(Integer.MAX_VALUE));
props.put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, 5); // イドポテンス有効時の既定と整合
// バッファ余裕をみて調整
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 67108864); // 64MB
// キー・値のシリアライザ
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.ByteArraySerializer");
KafkaProducer<String, byte[]> producer = new KafkaProducer<>(props);CCDAKでは、batch.sizeとlinger.msの役割、パーティション単位でバッチが形成される点、linger.ms=0でもサイズ条件のバッチングは起こる点が頻出です。batch.sizeはバイト単位であり件数ではありません。
また、圧縮がバッチ単位で実施されるため、バッチを大きくすることが圧縮率とスループットを押し上げる、という因果も問われます。逆に、低トラフィック下でlinger.msを大きくすると平均遅延を悪化させる点も定番の引っかけです。
CCDAK
問題 1
Kafka Producerにおいて、linger.msの正しい説明はどれか。
正解: A
linger.msは満杯でないバッチのための待機上限時間です。サイズ条件が先に満たされれば即送信されます。batch.sizeはバイト数であり件数ではありません。linger.ms=0でもサイズ条件によるバッチングは行われます。再送や順序は主にretries、acks、enable.idempotence、max.in.flightなどで制御されます。
少量トラフィックのトピックで、linger.msはどの程度がよいですか?
少量であれば5〜20msの範囲で試し、平均遅延とP95/P99を見ながら調整します。サイズ条件が満たされにくい状況ではlinger.msが平均遅延に直結するため、SLAが厳しければ5〜10ms程度に抑えるのが無難です。
batch.sizeを大きくするとメモリ不足になりませんか?
未送信バッチはbuffer.memoryから確保されるため、同時にアクティブなパーティション/接続が多いほど消費が増えます。段階的に引き上げ、batch-size-avg、bufferpool-wait-time、max.block.msの挙動を確認してください。必要ならパーティション数や並列度の設計も見直します。
linger.msを増やすとタイムアウトが増えますか?
linger.msは送信前の待機を増やしますが、delivery.timeout.ms(総配信上限)内で完了する限り即座にタイムアウトにはなりません。ただしトラフィックが極端に薄く、再送やブローカー遅延が重なると上限に近づく可能性があります。request.timeout.msやretriesとの整合性を保ってください。
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-...