在实际项目中,我们经常会遇到一种情况:Producer 发送消息很快,但 Consumer 就是消费不过来,Kafka 中的消息越积越多,Lag 也越来越高。
很多人的第一反应是:是不是 Kafka 消费性能不行?是不是把 max.poll.records 调大就好了?
实际上,大多数“Kafka 消费慢”问题并不是 Kafka 读取消息本身慢,而是整个消费链路中存在瓶颈。这个瓶颈可能出现在 Consumer 数量、Partition 数量、业务处理逻辑、数据库、远程接口、JVM、网络,甚至频繁 Rebalance 上。
本文从排查角度出发,讲清楚 Kafka 消费速度为什么会比生产速度慢,以及线上应该按照什么顺序定位性能瓶颈。

一、先搞清楚:什么叫“消费速度比生产速度慢”?
假设生产者每秒向 Kafka 写入:
30000 条消息 / 秒
而消费者每秒只能真正处理:
10000 条消息 / 秒
那么每秒就会新增:
30000 – 10000 = 20000 条积压消息
只要这种状态持续存在,Consumer Lag 就一定会不断增加。
因此,判断消费是否“跟得上”,最关键的不是某一瞬间有多少 Lag,而是观察:
Lag 是否持续增长;
消费速率是否长期低于生产速率;
某些 Partition 是否明显比其他 Partition 更慢;
Consumer 是否频繁发生 Rebalance;
消费程序本身是否存在 CPU、GC、数据库或网络瓶颈。
从整体上可以把消费吞吐量理解成:
最终消费吞吐量 ≈ 整条消费链路中最慢环节的吞吐量
也就是说,就算 Kafka 每秒能给你几十万条消息,如果你的数据库每秒只能写 1 万条,最终消费速度仍然只能接近 1 万条。
二、第一步:先看 Consumer Lag,而不是先改参数
排查消费慢,第一件事应该是确认 Consumer Group 当前到底积压了多少消息。
Kafka 自带的 kafka-consumer-groups.sh 可以直接查看 Consumer Group 的 Offset 和 Lag。
bin/kafka-consumer-groups.sh –bootstrap-server localhost:9092 –describe –group order-consumer-group
典型输出会包含:
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG
order 0 120000 180000 60000
order 1 135000 180000 45000
order 2 178000 180000 2000
这里重点看:
字段含义
CURRENT-OFFSET当前 Consumer Group 已经消费到的位置
LOG-END-OFFSETPartition 当前日志末尾位置
LAGConsumer 还落后多少条消息
如果 LAG 一直增加,就说明消费速度确实长期小于生产速度。
如果只是偶尔出现 Lag,随后又快速降到 0,则可能只是正常的流量尖峰,并不一定代表系统存在严重性能问题。
还可以查看 Consumer 与 Partition 的分配情况:
bin/kafka-consumer-groups.sh –bootstrap-server localhost:9092 –describe –group order-consumer-group –members –verbose
这一步可以直接看出:到底有多少 Consumer 真正在工作,每个 Consumer 分到了哪些 Partition。
三、最常见瓶颈之一:Consumer 数量不够
Kafka 的并行消费能力和 Partition 有非常直接的关系。
对于普通 Consumer Group,同一个 Partition 在同一时刻只会分配给 Group 中的一个 Consumer。
例如一个 Topic 有 6 个 Partition,如果 Consumer Group 中只有 2 个 Consumer,那么每个 Consumer 可能需要处理 3 个 Partition。
如果单个 Consumer 已经达到性能上限,这时增加 Consumer 数量通常可以提升整体消费能力。
但是 Consumer 并不是越多越好。

假设 Topic 只有 6 个 Partition,却启动了 10 个 Consumer,那么最多仍然只有 6 个 Consumer 能得到 Partition,其余 Consumer 会处于空闲状态。
可以记住:
普通 Consumer Group 的有效并行度上限通常受 Partition 数量限制
因此看到消费慢时,不要直接“多启动几个消费者”,而应该先看:Topic 有多少 Partition、Consumer Group 有多少 Consumer、是否有 Consumer 空闲,以及 Partition 之间的 Lag 是否均衡。
四、最常见的真正瓶颈:业务处理逻辑太慢
很多时候,Consumer 从 Kafka 拉消息其实很快,真正慢的是消费后的业务代码。
例如消费一条订单消息后,需要反序列化 JSON、查询 MySQL、更新库存、写订单表、调用远程 HTTP 接口、写 Redis、打印日志。
如果每条消息平均耗时 20ms,那么一个线程理论上每秒最多只能处理:
1000 / 20 = 50 条
即使 Kafka 一次给你拉回来 500 条消息,业务代码仍然可能处理很久。
高吞吐场景中,“消费一条就执行一次 INSERT/UPDATE”通常会产生大量网络往返和事务提交开销。业务允许时,可以考虑批量写入。
如果消费线程里同步调用平均耗时 100ms 的 HTTP 接口,吞吐量很容易直接被这个接口拖垮。
需要重点观察平均 RT、P95/P99、超时次数、重试次数和连接池是否耗尽。
高频消费代码如果每条消息都打印大量 INFO 日志,也可能产生明显的磁盘与锁竞争开销。
五、不要误解 max.poll.records
很多文章一看到消费慢就建议把:
max.poll.records=1000
但这里很容易误解。
max.poll.records 控制的是:一次调用 poll() 最多返回给应用程序多少条记录。
它不会改变 Consumer 底层 Fetch 请求本身的拉取行为。Consumer 会缓存 Fetch 回来的数据,再根据 max.poll.records 分批返回给应用程序。
Kafka 4.3.1 默认值为:
max.poll.records=500
所以把它从 500 调成 1000,并不意味着网络层立刻“每次多拉一倍数据”。如果一批消息处理时间已经很长,盲目调大反而可能让一次业务处理持续更久。
六、真正影响 Fetch 批次的几个参数

表示 Broker 在响应 Fetch 请求前,希望至少准备多少数据。Kafka 4.3.1 默认:
fetch.min.bytes=1
适当调大可以让 Broker 尽量攒更多数据再返回,从而减少请求次数、提高吞吐,但代价是可能增加消费延迟。
2. max.partition.fetch.bytes
控制单个 Partition 在一次 Fetch 响应中最多返回多少数据。Kafka 4.3.1 默认:
max.partition.fetch.bytes=1048576
约 1 MiB。
3. fetch.max.bytes
控制一次 Fetch 请求最多返回多少数据。Kafka 4.3.1 默认:
fetch.max.bytes=52428800
约 50 MiB。
可以简单理解为:
max.partition.fetch.bytes → 限制单个 Partition
fetch.max.bytes → 限制整个 Fetch 请求
七、下游数据库可能才是真正的“限速器”
假设 Kafka Consumer 理论处理能力是 50000 条/秒,而 MySQL 最大稳定写入能力只有 12000 条/秒,那么整条系统最终稳定吞吐量不可能长期超过 12000 条/秒。
继续增加 Consumer 甚至可能让数据库连接池耗尽、锁竞争增强、慢 SQL 增加、CPU 飙升、磁盘 I/O 变高。
下游组件重点检查
MySQLQPS、慢 SQL、连接池、锁等待、CPU、I/O
RedisQPS、网络延迟、慢命令、连接池
HTTP/RPCRT、P95/P99、超时、重试
ElasticsearchBulk 大小、写入拒绝、Refresh 压力
八、处理时间过长可能触发 Rebalance
一个非常重要的参数是:
max.poll.interval.ms=300000
Kafka 4.3.1 默认是 5 分钟。
它限制了使用 Group Management 时两次 poll() 调用之间允许的最大间隔。应用拿到一批消息后如果处理太久,迟迟不能再次调用 poll(),超过该时间后可能触发 Partition 重新分配。
这可能形成:
业务处理慢
↓
poll 间隔过长
↓
Rebalance
↓
消费受到影响
↓
Lag 继续增加
Kafka 4.0 起的新 Consumer Rebalance Protocol 已经采用增量式设计来降低 Rebalance 时间,但应用处理过慢和成员不稳定仍然需要排查。
九、JVM 的 CPU 和 GC 也可能拖慢消费
Kafka Consumer 是 Java 程序时,还要检查 JVM 本身。
CPU 长期接近 100%、JSON 序列化开销过大、线程太多导致上下文切换、频繁 Young GC/Full GC、对象分配速率过高,都可能让 Consumer 无法及时处理消息。
Kafka 官方监控文档也建议同时监控 GC、CPU、I/O 等系统指标,而不是只盯 Kafka 指标。
十、业务逻辑没问题,再看 Kafka Fetch 是否真的慢
Kafka Consumer 提供了很多关键指标:
指标作用
records-consumed-rateConsumer 每秒平均消费多少条记录
records-lag-max当前窗口内任一 Partition 的最大 Lag
fetch-latency-avgFetch 请求平均耗时
fetch-size-avg平均一次 Fetch 返回多少字节
records-per-request-avg平均每个请求返回多少记录
fetch-throttle-time-avgFetch 平均被限流多久
如果 records-lag-max 持续增长,而 records-consumed-rate 明显不足,就继续判断是应用处理慢、Fetch 慢还是 Broker 被限流。
十一、Broker 或网络本身也可能成为瓶颈
如果多个 Consumer 同时变慢,而应用业务代码没有明显变化,就需要看 Broker 端。
重点检查:Broker CPU、磁盘 I/O、网络吞吐、Request Queue、Fetch 响应时间、Network Processor 空闲率、Throttle 和副本同步压力。
如果生产和消费同时下降,更要优先怀疑 Broker、网络或整个集群层面的资源问题。
十二、线上建议按照这个顺序排查

第 1 步:确认 Lag 是否真的持续增长
bin/kafka-consumer-groups.sh –bootstrap-server localhost:9092 –describe –group order-consumer-group
第 2 步:检查 Partition 与 Consumer 数量
确认 Partition 数、Consumer 数、每个 Consumer 的 Partition 分配,以及是否有 Consumer 空闲。
第 3 步:测量业务代码真正耗时
分别记录拉取一批消息耗时、业务计算耗时、数据库耗时、远程接口耗时和 Offset 提交耗时。
第 4 步:检查下游系统
如果数据库已经达到极限,应优化数据库或批量写入,而不是继续增加 Consumer。
第 5 步:查看 Consumer Fetch 指标
records-consumed-rate
records-lag-max
fetch-latency-avg
fetch-size-avg
records-per-request-avg
fetch-throttle-time-avg
第 6 步:检查 Rebalance
观察 Consumer 日志和 Group 状态,确认是否频繁重新分配 Partition。
第 7 步:检查 JVM 和机器资源
CPU
内存
GC
线程池
网络
磁盘
第 8 步:最后再有针对性地调 Kafka 参数
max.poll.records=500
fetch.min.bytes=1
max.partition.fetch.bytes=1048576
fetch.max.bytes=52428800
max.poll.interval.ms=300000
参数调优应该根据监控结果进行,而不是简单地全部调大。
十三、几个非常常见的错误优化方式
错误 1:消费慢就疯狂增加 Consumer
如果 Partition 只有 6 个,Consumer 增加到 20 个并不会让 20 个实例同时消费这 6 个 Partition。
错误 2:直接把 max.poll.records 调到几万
一次返回太多消息可能导致单批业务处理时间更长,甚至增加超过 max.poll.interval.ms 的风险。
错误 3:数据库已经扛不住,还继续扩 Consumer
这相当于高速公路出口已经堵死,还继续增加入口车辆,只会让下游更拥堵。
错误 4:只看总体 Lag,不看 Partition Lag 分布
如果只有一个 Partition 的 Lag 特别高,可能是数据倾斜、Key 分布不均、大消息或某个 Consumer 异常。
错误 5:只把 max.poll.interval.ms 调大
如果业务确实处理太慢,单纯扩大超时时间只是让 Kafka 更晚发现问题,并没有提升实际吞吐量。
十四、一个简单的性能估算方法
假设一个 Consumer 平均每条消息业务处理耗时 5ms,单线程理论处理能力大约为:
1000 / 5 = 200 条/秒
如果启动 6 个 Consumer:
6 × 200 = 1200 条/秒
而生产速度是:
5000 条/秒
那么每秒仍然会新增:
5000 – 1200 = 3800 条积压
真正的优化方向应该是降低单条处理耗时、批量操作数据库、在 Partition 允许时增加 Consumer、把耗时任务异步化,以及提升下游服务能力。
十五、总结
Kafka 出现“生产快、消费慢”时,最重要的不是立刻调参数,而是先确定瓶颈在哪一层。
Producer
↓
Kafka Broker
↓
Fetch
↓
Consumer
↓
业务逻辑
↓
MySQL / Redis / HTTP / ES
实际排查可以记住:
先看 Lag
↓
再看 Partition / Consumer 并行度
↓
再看业务处理时间
↓
再看数据库和远程接口
↓
再看 Rebalance、CPU、GC
↓
最后再看 Fetch 参数、Broker 和网络
Kafka Consumer 性能优化的核心不是“把某个参数调大”,而是找到整条消费链路中最慢的那个环节,然后有针对性地解决。
参考资料
Apache Kafka 4.3 – Consumer and Share Consumer Configs
Apache Kafka 4.3 – Monitoring
Apache Kafka 4.3 – Basic Kafka Operations
Apache Kafka 4.3 – Consumer Rebalance Protocol




