Kafka

Kafka Producerの batch.size と linger.ms: スループットと遅延を両立させる設計

2026-04-19
NicheeLab編集部

Kafka Producerはレコードをパーティション単位でバッチ化して送信します。batch.sizeは1バッチの最大バイト数、linger.msは満杯でない場合に追加レコードを待つ上限時間です。

本稿は公式ドキュメントの安定動作に基づき、スループットと遅延SLAのバランスを取るための具体的な指針を示します。CCDAK向けの要点整理と、現場で迷いがちな落とし穴もカバーします。

batch.size と linger.ms の基本と使い分け

batch.sizeはパーティションごとの1送信バッチの最大サイズ(バイト)です。実際のバッチサイズは直近に蓄積できたデータ量で決まり、上限としてbatch.sizeが効きます。多数の小レコードでネットワーク効率を上げたい場合や圧縮効率を上げたい場合に増やします。

linger.msは、バッチが満杯でないときに追加のレコードを待つ最大時間(ミリ秒)です。満杯になれば待たずに送信されます。よって、トラフィックが低い時間帯でもある程度まとめて送ることができますが、その分だけ待機遅延が増えます。デフォルトは一般に0msで、待ち時間を持たず即時寄りに送信します。

重要な前提として、バッチはパーティション単位で形成されます。多パーティションに一様に書き込む場合、同時に複数の未送信バッチが存在しうるため、batch.sizeの設定はbuffer.memoryの消費にも影響します。

  • 低遅延重視: linger.msを0〜2ms、batch.sizeは16KB〜32KB程度から開始
  • バランス型: linger.msを5〜15ms、batch.sizeは32KB〜64KB程度
  • 高スループット重視: linger.msを20〜50ms、batch.sizeは64KB〜128KB以上も検討(SLAとメモリに注意)
  • いずれの場合もcompression.typeをlz4またはzstdにすることで、バッチが大きいほど圧縮効率が上がりスループット向上が見込める
プロファイルbatch.size(目安)linger.ms(目安)特徴
低遅延16〜32KB0〜2ms最小の送信待機。小バッチ多発でネットワーク効率はやや低い
バランス32〜64KB5〜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ではバッチ効率を高めるためにパーティショニング戦略が改善されていますが、本質は「パーティション単位の蓄積と、サイズ・時間の二重条件での送信」です。このメカニズム自体はバージョンに依存せず安定しています。

  • 送信トリガ: サイズ上限到達 または linger.ms到達(いずれか早い方)
  • 圧縮はバッチ単位: 大きいバッチほど圧縮率が上がる傾向
  • メモリはbuffer.memoryからプールされ、同時未送信バッチ数が増えると消費も増える

Producerのバッチ形成と送信の概念図

produce()(App code)RecordAccumulator(per-partition buf)Sender threadsize/time triggerBroker送信トリガ: batch.size 到達 または linger.ms 到達(いずれか早い方)

遅延予算とSLAからの逆算設計

エンドツーエンド遅延SLA(例: P99 ≤ 200ms)から逆算し、プロデューサ側で許容できる送信待機時間を決めます。linger.msは最悪ケースでそのまま待機遅延に加算されうるため、ネットワークとブローカー応答(acks)にかかる平均/分位数レイテンシを差し引いて上限を設定します。

たとえば、ブローカー往復(acks=all)のP99が80ms、アプリ処理が50msなら、プロデューサ側で許せる待機は概ね70ms以内です。ただし、レコード到着間隔が疎なときはlinger.msに達してから送信されることが多くなるため、平均遅延を押し上げます。SLAが厳しい場合は小さめに、到着レートが高い場合はサイズトリガが先に効くのでlinger.msをやや大きくしても実遅延影響は限定的です。

  • SLA逆算: 予算 = 目標P分位遅延 − (アプリ処理 + ブローカー往復 + 下流処理)
  • 到着レート高: サイズトリガ優勢 → linger.msの影響は小さい
  • 到着レート低: 時間トリガ優勢 → linger.msが平均遅延を押し上げる
  • delivery.timeout.msは全体の配信上限時間。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の上限を調整します。公式実装では、イドポテンス有効時に重複排除と順序保証が強化されます。

  • buffer.memoryの監視: bufferpool-wait-time、records-per-request、batch-size-avg
  • max.block.msに達するブロックは過大なbatch.sizeや低速ネットワークの兆候
  • enable.idempotence=true と acks=all を既定に。古いクライアント併用時は互換性に留意
  • スループット向上はcompression.typeとbatch/lingerの相乗で得る。無制限な再送は避ける

実運用チューニング手順(安全な手順と検証ポイント)

前提として、ステージングまたは隔離可能なトピックで検証します。指標は平均だけでなく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や、アプリ内でワークロード相当のメッセージサイズ分布を再現して測ると、設定の効果が読み取りやすくなります。

  • 最初に圧縮方式を見直す(効果が大きい)
  • batch.sizeを上げる前にbuffer.memoryの余裕を確認
  • linger.msはP99遅延を見ながら5ms刻みで微調整
  • max.in.flightとretriesはブローカー安定度に応じて調整
  • delivery.timeout.msとrequest.timeout.msの関係を崩さない

プロデューサ設定例(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試験向けの要点と落とし穴

CCDAKでは、batch.sizeとlinger.msの役割、パーティション単位でバッチが形成される点、linger.ms=0でもサイズ条件のバッチングは起こる点が頻出です。batch.sizeはバイト単位であり件数ではありません。

また、圧縮がバッチ単位で実施されるため、バッチを大きくすることが圧縮率とスループットを押し上げる、という因果も問われます。逆に、低トラフィック下でlinger.msを大きくすると平均遅延を悪化させる点も定番の引っかけです。

  • バッチはパーティション単位。到着レートが高いとlinger.msの影響は相対的に小さい
  • linger.ms=0でも満杯時は即送信、つまりバッチング自体は存続
  • batch.sizeは上限バイト数。大きくするとbuffer.memoryの消費ポテンシャルが増える
  • 圧縮はバッチ単位。大きいバッチほど効果的(ただしCPUと遅延のトレードオフ)

問題で確認

CCDAK

問題 1

Kafka Producerにおいて、linger.msの正しい説明はどれか。

  1. バッチが満杯でない場合に追加レコードを待つ最大時間であり、バッチが満杯になれば待たずに送信される
  2. レコードの最大件数を指定する設定である
  3. 0に設定するとバッチングは完全に無効化され、各レコードが個別送信される
  4. ネットワークの再送回数を制御し、順序保証にのみ影響する

正解: 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との整合性を保ってください。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Kafka

Kafka Topic と Partition の基礎: 分散とスケーラビリティの要

CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...

Kafka

CCDAK 試験ガイド:出題範囲・配点・申込み・対策

Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...

Kafka

Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点

CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...

Kafka

Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性

レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...

Kafka

Kafka の Offset とコミット: ポジション管理と at-least-once の基礎

CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...

Kafkaの記事一覧 (101件)
© 2026 NicheeLab All rights reserved.