Spring-Kafka框架下为何固定出现Partition 9消息积压问题?
Range分区分配策略下固定Partition积压原因分析
环境配置
- SpringBoot版本:2.3.7
- Spring Kafka版本:2.7.2
- 消费组:单消费组,订阅两个topic:
- Topic A:30个分区,生产速度均衡
- Topic B:3个分区,生产速度均衡且消息量更少
- 消费参数:
concurrency=8,max.poll.records=50,分区分配策略为Range
Range分配策略核心逻辑
Range策略会按单个topic维度独立计算分区分配:
- 将当前topic的所有分区按序号从小到大排序
- 用分区总数除以consumer数量,得到每个consumer基础分配的分区数
- 若有余数,前N个consumer(N=余数)会多分配1个分区
本次场景的分区分配明细
Topic A(30个分区)
30 ÷ 8 = 3,余数6,因此前6个consumer各分配4个分区,后2个consumer各分配3个分区:
- Consumer 0:A-0 ~ A-3
- Consumer 1:A-4 ~ A-7
- Consumer 2:A-8 ~ A-11 (重点关注的consumer)
- Consumer 3:A-12 ~ A-15
- Consumer 4:A-16 ~ A-19
- Consumer 5:A-20 ~ A-23
- Consumer 6:A-24 ~ A-26
- Consumer 7:A-27 ~ A-29
Topic B(3个分区)
3 ÷ 8 = 0,余数3,因此前3个consumer各分配1个分区,其余consumer不分配B的分区:
- Consumer 0:B-0
- Consumer 1:B-1
- Consumer 2:B-2 (与A-8~11分配给同一个consumer)
Partition 9积压的原因
- 分区负载集中:Consumer 2需要同时处理5个分区(4个A分区+1个B分区),是所有consumer中处理分区数量最多的——其他consumer最多处理4个A分区,或3个A分区+0/1个B分区,负载压力更大。
- 拉取额度被稀释:
max.poll.records=50是consumer一次poll拉取的总消息条数上限,不是单个分区的上限。Consumer 2从5个分区分配这50条额度,每个A分区能分到的消息数会被稀释(比如平均每个A分区仅能分到约10条),而其他只处理4个A分区的consumer,每个分区能分到约12-13条,拉取效率更低。 - Broker IO竞争:从日志观察到A-9与B-2位于同一个broker,同一broker上的两个分区同时拉取消息时,会占用该broker的网络IO资源,进一步降低A-9的拉取速度,导致消息处理速度跟不上生产速度,最终出现固定积压。
提升concurrency后,单个consumer分配的分区数量减少,总处理能力提升,拉取额度的稀释效应消失,因此所有分区无积压。
内容的提问来源于stack exchange,提问作者TheShyLikeCoding
相关产品推荐
相关产品推荐

