如果还没开始投入使用 Kafka,那应该在设计分区数的时候,尽量设置的多点(当然也不要太大,太大影响延迟,具体可以参考我前面提到的文章),从而提升生产和消费的并行度,避免消费太慢导致消费堆积。

增大批次

瓶颈在消费吞吐量的时候,增加批次也可以改善性能

增加线程数

如果一些消费者组中的消费者线程还是有 1 个消费者线程消费多个分区的情况,建议增加消费者线程。尽量 1 个消费者线程对应 1 个分区,从而发挥现有分区数下的最大并行度。

分区数预设计、增大批次、增加线程三条是消费侧提速的正确动作,但堆积治理的完整方法论还缺三块:堆积的根因分类(消费慢 vs 生产突增 vs 消费者故障)、紧急处置预案(积压已发生怎么办)、以及预防体系(监控与容量)。本文补全。

根因分类:先诊断再动手

根因 信号 对策方向
消费逻辑慢 单条处理耗时长(含下游 RPC/DB 慢) 优化消费逻辑/批量/并行
消费者数不足 分区数 > 消费者数,或线程<分区 扩消费者/线程(原文第三条)
生产突增 生产速率曲线尖峰(活动/重试风暴) 上游限流/削峰设计复核
消费者故障/假死 消费者在线但不消费(GC/死锁/ rebalance 循环) 修消费者/重启/查 rebalance 日志
下游故障传导 消费逻辑等下游超时 熔断下游+消费降级/暂存

先看监控再动手:lag 曲线 + 生产/消费速率 + 消费者数 + 单条耗时四指标定位根因;盲目加消费者在”消费逻辑慢且下游已饱和”时只会把压力转嫁给下游。

消费侧提速(原文三条的展开)

  • 分区数是并行度上限(Kafka):消费者数 > 分区数无意义;设计期按峰值吞吐 × 冗余预估分区(原文第一条)
  • 批量消费:max.poll.records 调大 + 批量写库/批量 RPC(把 N 次 IO 变 1 次);注意批量大小与处理延迟的权衡
  • 线程模型:消费者线程拉取+分发,工作线程池并行处理(注意:并行处理破坏分区序,需按 key 哈希到固定线程保序)
  • 消费逻辑瘦身:重计算/富化移到消费后异步;非核心环节降级跳过(先保主流程消化)

紧急处置预案(积压已发生的三板斧)

  1. 扩:消费者扩到分区数上限;Kafka 分区不够时临时扩容分区(注意:扩分区改变 key 路由,顺序语义与消费者 rebalance 需评估)
  2. 转:新建”转发 topic”(分区数大),原消费者改为纯转发(只搬不处理),新消费者群并行消化——把积压从”慢处理”变为”快搬运+并行处理”两级
  3. 弃:业务允许时(如过期通知类),定位移过积压段(seek to end)或缩短消息 TTL 让旧消息过期——承认部分消息放弃,保系统存活(需业务确认+事后补偿)

配套:上游限流止血(防继续涌入)、下游保护(消费提速别打垮 DB:消费侧限流/批量控速)。

预防体系

  • lag 监控告警:消费 lag(条数+时间维度:最老未消费消息年龄)双指标告警,时间维度更早发现”消费停摆”
  • 容量规划:分区数按”峰值消费并行度”预留(扩分区有成本,预留在设计期便宜)
  • 消费幂等与重试隔离:重试消息进独立重试 topic,不让重试流量与正常流量抢消费能力(重试风暴是隐性堆积源)
  • 演练:定期停消费者制造积压再恢复,验证告警与预案有效性

一个复盘案例

大促后积压 800 万条:监控发现单条消费 200ms(含 3 次 RPC)→ 根因=消费逻辑慢而非消费者少 → 处置=批量改造(20 条/批 RPC 合并)+ 消费者扩至分区数 + 非核心富化环节降级 → 40 分钟消化完毕。复盘结论:先测单条耗时再决定扩什么——扩消费者只对”并行度不足”有效,对”单条太慢”要先优化逻辑。

堆积治理 = 诊断(四指标定根因)→ 提速(分区/批量/线程/瘦身)→ 应急(扩/转/弃三板斧)→ 预防(lag 双指标+容量+重试隔离+演练)四层;记住”分区数是并行度天花板”与”重试流量要隔离”两条,多数堆积事故都能提前避免或快速消化。