面试记录 2026-10-12
题目:RocketMQ消费堆积问题排查
难度:high
标签:practice/debug, mq/rocketmq, difficulty/high
评分:⭐⭐⭐☆☆(3/5)
我的回答
首先确定原因,查看监控,是生产端产生了过多的生产内容吗?还是说消费端出现了问题?这个可以通过对应的请求接口、日志、监控去查看。查看到了具体原因,是生产者突发生产过多,还是消费者出现了消费异常。
这个消息积压是否影响了整体的业务?如果没有影响,看是否可以正常的消费完。如果不行的话,就进行消费端的增加。
如果是生产者生产突然病发,这个积压可以正常的消费完。如果短时间内可以消费完,不用处理。如果这个积压短时间内消费不完,就增加消费端的能力。比如先起一个新的 Topic 把这些消息进行迁移,然后对应的再起消费者去消费这些暂时无法处理的消息。
如果是消费端出现了异常,检查排查具体的问题原因,是依赖的服务出现问题了,还是生产消费者出现了服务宕机之类的问题。如果是这类问题,先检查是依赖组件还是怎么样,尽量先处理这样问题。然后可以依照刚刚的方案,先把这些积压的消息转移到其一个新的 Topic 上,等待业务恢复之后,再把这些积压的消息进行统一处理,防止整个消息体线路的崩溃。
我的核心想法还是先确定原因,确定原因之后把消息转移,然后缓慢消费。因为 MQ 本身是一个削峰填谷的东西,你既然已经放进去了,就可以先保证它继续的先把这个问题转移出去。
点评
优点:
- 排查思路框架合理:先定位原因(生产端 vs 消费端)→ 再看业务影响,逻辑清晰
- 意识到区分"生产突增"和"消费异常"是排查第一步
- 有兜底意识——"处理依赖问题优先于其他操作"
- 最后总结"先确定原因再处理",方法论意识到位
不足:
- 具体排查工具完全没提——应该提 RocketMQ Dashboard、Consume TPS vs Produce TPS、Consumer Progress、Consume Queue Size 等
- 技术动作太模糊——"增加消费端能力"具体怎么做?应该是扩容消费者 + 调大
consumeThreadMax + 确认 Partition 分配均衡
- "把消息迁移到新 Topic"这个方案在 RocketMQ 里不太常见——常规做法是让现有消费者扩容追消息;迁移是更重的动作,通常只在需要隔离毒丸消息时才做
- 完全没考虑消息过期风险——堆积到 100 万级,超过
fileReservedTime 会被清理,业务上是否可接受?
- 完全没考虑业务影响评估——堆积期间新消息是否正常?延迟 SLA 是多少?
- 没提根因排查的常见类别:Consumer 处理慢(DB 慢查询、下游超时、锁竞争)、rebalance、消费者掉线
补充:
- 看现象:Consume TPS vs Produce TPS、堆积量、堆积增长速率、消费延迟
- 看分布:堆积集中在哪些队列/消费者?是否有消费者"空转"?
- 看日志:消费者端 GC、慢方法、异常日志;下游依赖 RT
- 看变更:最近发布/配置变更?生产者侧新增流量?
- 决策:扩容消费者(首选)→ 临时降级非关键业务 → 隔离毒丸消息 → 迁移新 Topic(最后手段)
完整讲解
第一部分:知识重点剖析
核心考点定位:考察候选人面对线上堆积故障时的排查方法论 + 处置优先级 + 风险控制意识。堆积是 MQ 最典型的线上事故,能否快速定位并安全缓解,是高级工程师的基本功。
知识点拆解:
- 第一步:看现象(30 秒内建立基本判断)
- 看堆积量、堆积增长速率、消费延迟(
ConsumeLatency)
- 看 Consume TPS vs Produce TPS 曲线:消费慢 → 消费者问题;生产突增 → 生产端或业务侧问题
- 看堆积是否集中在某些队列(Rebalance 导致分配不均?某些队列有"卡消息"?)
- 第二步:看分布(判断是全局问题还是局部问题)
- Dashboard 上每个 Queue 的堆积量、每个 Consumer 的 TPS
- 是否有 Consumer 长时间不消费("空转"消费者)?
- Consumer Group 是否处于 rebalance 状态?
- 第三步:看消费者端(定位根因)
- 消费者日志:异常栈、慢方法、GC 情况
- 下游依赖:DB 慢查询、下游 RPC 超时、锁竞争
- 消息体:是否有异常大的消息导致处理慢?是否有"毒丸消息"反复重试?
- 第四步:看变更
- 最近发布/配置变更?
- 生产者侧是否有新流量(大促、爬虫、重试风暴)?
- 基础设施:网络抖动、Broker GC、磁盘慢
- 第五步:处置决策(按优先级)
- 首选:扩容消费者(水平扩展,最快见效)
- 次选:调大
consumeThreadMax、批量消费调优
- 降级:临时跳过非关键业务逻辑
- 隔离:把"毒丸消息"移到死信队列
- 最后:迁移到新 Topic(重动作,会中断消费流程)
堆积排查的核心思路:先看现象再定根因,先扩容再优化,先隔离再重建。
第二部分:考察方向与延伸递进
考察方向:
- 深度:RocketMQ 的
pullBatchSize 和 consumeMessageBatchMaxSize 调优、堆积时的 Consume Queue Size 计算、Consumer 消费线程池拒绝策略
- 广度:与 Kafka 堆积排查对比(Kafka 看 Consumer Lag)、与 RabbitMQ 堆积对比(Quorum Queue)
- 应用:如何设计堆积告警阈值、如何演练消费者扩容、如何在堆积时保持消费者稳定
延伸递进面试题:
- 堆积到 100 万条,扩容消费者有用吗?
- 解答要点:如果瓶颈在下游 DB,扩容消费者只会加剧 DB 压力;要同时扩容下游能力或限流
- 如何判断"堆积可控"?
- 解答要点:堆积增长速率 ≤ 消费速率 → 堆积会自然消退;反之需要干预
- 消费者扩容到 100 个实例,堆积为什么没减少?
- 解答要点:RocketMQ 每个 Queue 只能被一个消费者消费;如果 Queue 数 < 消费者数,多出的消费者空转
- 如何避免堆积再次发生?
- 解答要点:告警阈值 + 消费者 SLA + 下游容量规划 + 压测
第三部分:面试者参考回答(300-500 字口语化)
面试官您好,堆积从 1000 涨到 100 万,我会分五步走。
第一步,看现象:先看 Dashboard 的堆积量、消费延迟、Consume TPS 和 Produce TPS 曲线。如果消费 TPS 明显低于生产 TPS,说明是消费侧的问题;如果生产 TPS 突然飙升,说明是生产端问题(比如上游重试风暴或大促流量)。这一步能快速判断方向。
第二步,看分布:堆积是否集中在某些 Queue?是否有 Consumer 长时间不消费?Consumer Group 是否在 rebalance?如果是局部问题,可能有个别消费者挂了或有"毒丸消息"阻塞了某个 Queue。
第三步,看消费者端:翻消费者日志,看异常栈、慢方法、GC 情况;同时看下游依赖(DB、RPC)的 RT 是否飙高。堆积 100 万这种情况,最常见的根因是消费者处理慢——DB 慢查询、下游超时、锁竞争。
第四步,看变更:最近有没有发布?有没有新流量接入?如果和变更相关,评估是否需要回滚。
第五步,处置:
- 首选扩容消费者实例(最快见效,前提是 Queue 数 ≥ 消费者数)
- 同时限流或降级:堆积期间临时跳过非关键逻辑
- 如果发现有"毒丸消息"反复重试,把它移到死信队列,避免阻塞整个 Queue
- 严重情况才迁移到新 Topic——这是重动作,通常最后才考虑
风险意识:堆积 100 万条要评估两个风险:一是消息过期(超过 fileReservedTime 会被清理),二是消费者追消息时的性能退化(可能拖垮下游)。所以除了扩容消费者,还要评估下游容量,必要时先扩容 DB 或加缓存。
一句话总结:先扩容再优化,先隔离再重建。MQ 的堆积是"削峰填谷"的正常表现,关键是让堆积能被消费者追上,而不是让下游被打挂。