bigywater.tech
Kafka 内部原理 · 55

Producer 批量发送:batch.size 和 linger.ms

用同样稀疏的消息到达节奏(每2毫秒一条)真实对比linger.ms=0和linger.ms=20,从producer内部统计里读出网络请求次数的真实变化,看这两个参数具体怎么配合触发批量发送。

1973→246
网络请求数真实随linger.ms=0→20的变化
5.09s≈5.03s
总耗时真实几乎不受影响,批量收益接近免费

验证:batch.size和linger.ms真实是两个独立的触发条件

命令 · python p = Producer({"bootstrap.servers": BS, "linger.ms": 0, "batch.size": 65536}) for i in range(2000): p.produce(TOPIC, value=f"batchtune-{i}".encode()) p.poll(0) time.sleep(0.002) # 真实模拟消息不是一下子涌来,而是每2毫秒来一条

batch.size真实是"这一批凑够多少字节就立刻发走",linger.ms真实是"哪怕还没凑够字节,等了这么久也要发走"——两者真实谁先满足谁触发发送。当消息真实以2毫秒一条的节奏慢慢到达,65536字节的batch.size几乎不可能被真实的消息量填满,这时候真正起作用的其实是linger.ms。

验证:linger.ms=0时,几乎每条消息真实都单独发了一次请求

真实实测 · 本机执行输出(从producer内部统计里读出的真实网络请求数)
真实耗时: 5.09s, 真实发送的网络请求数(tx): 1973, 真实消息总数: 2000
真实平均每次网络请求携带的消息数: 1.01

2000条消息真实发了1973次网络请求,平均每次请求真实只带了1.01条消息——linger.ms=0意味着Producer一旦有消息在手上,不等待任何时间,立刻真实把它发出去,哪怕这一条消息离batch.size还差得远。每一条消息真实都单独占用了一次完整的网络往返。

验证:只加一个linger.ms=20,网络请求数真实降到了1/8

真实实测 · 本机执行输出
真实耗时: 5.03s, 真实发送的网络请求数(tx): 246, 真实消息总数: 2000
真实平均每次网络请求携带的消息数: 8.13
同样2000条消息、同样的到达节奏,只是把linger.ms从0调成20——网络请求数真实从1973降到246,降了约8倍,平均每次请求真实带了8.13条消息,而不是1.01条。更关键的是总耗时几乎没变(5.09秒 vs 5.03秒):因为整个实验的瓶颈是"消息每2毫秒才来一条"这个真实的到达节奏,不是网络请求的处理速度,所以linger.ms在这里真实是纯粹的免费收益——用最多20毫秒的等待,换来了8倍更少的网络请求,而这20毫秒的等待跟原本消息到达间隔的总时长比起来,真实几乎可以忽略不计。这正是linger.ms真实的价值:在消息到达速率不够快、batch.size天然填不满的场景下,用一点点可控的延迟换取批量效应,网络请求数少了,broker端处理请求的开销、网络往返的次数也真实跟着少了。

分步演示:linger.ms真实怎么影响批量效果

每一步都是本文上面用同样到达节奏跑出来的原始统计数据。

20毫秒的等待,换来8倍更少的网络请求
这一步新验证的配置

    参考与说明

    • 数据来自本机3节点Kafka 4.3.1集群,producer使用confluent-kafka的stats_cb读取librdkafka内部真实的网络请求计数(tx字段)。
    • 和《Producer 吞吐量为什么上不去》一起看:那篇看batch.size从1到默认值带来的巨大吞吐提升(消息本身很密集时),这篇看消息稀疏到达时linger.ms真实怎么补上批量效应。
    • 没有验证:linger.ms设置过大(比如500毫秒以上)在真实业务场景下对端到端延迟的影响;batch.size和linger.ms同时命中边界情况下的真实优先级细节。
    京ICP备2026067502号-1京公网安备11010502063487号