← 返回面试专题

📮 MQ 堆积:消费延迟、重试风暴与削峰填谷

核心目标:先恢复消费,再定位瓶颈,最后完善重试/幂等/限流

🧩 场景题题干(面试官常用表述)

现象:Kafka/RabbitMQ/RocketMQ 堆积严重,延迟越来越大。 你怎么判断是生产太快还是消费太慢? 怎么快速恢复?怎么避免重试风暴?
💡 一句话思路:先算“积压能否被追上”(消费能力 vs 生产速度),再做短期扩容/并发提升/批处理,最后用限流、死信队列、幂等与降级治理重试风暴。

📚 学习正文:MQ 堆积如何定位到“具体瓶颈/具体消费者/具体下游”?

1) 先止血:让积压不再继续扩大

止血目标:让 消费速率 ≥ 生产速率 手段:降低生产(限流/降级) + 提升消费(扩容/并发/批处理) + 隔离失败/慢消息(死信/重试隔离)

2) 先把问题量化:追得上吗?需要多久恢复?

关键公式: 恢复时间 ≈ 当前积压量 / (消费速率 - 生产速率) 如果 消费速率 ≤ 生产速率:积压只会越来越大,必须先控生产或扩分区/扩并发。

3) 证据链:定位“慢在 MQ 还是慢在下游”

4) 快速恢复的工程手段

5) 如何避免重试风暴(最容易把系统拖垮)

退避重试(指数退避+抖动) 区分可重试/不可重试(业务拒绝直接死信) 重试链路与主消费链路隔离资源 消费幂等 + 业务唯一约束兜底

6) 长期治理

监控:lag/积压量/失败率/重试次数/死信量 容量:分区数与并发度规划 演练:下游不可用/重试风暴演练 治理:热点 key 分片,避免单分区热点

🎯 面试题(建议学完上面正文再做)

1. MQ 堆积常见根因有哪些?简单
  • 消费变慢:下游(DB/Redis/第三方)慢、锁竞争、线程池耗尽。
  • 消费失败重试:异常导致反复重试,吞吐下降(重试风暴)。
  • 生产暴增:活动/大促/异常流量,生产速度超过消费能力。
  • 分区/队列不均:热点 key 导致某个分区被打爆。
2. 如何快速判断“追得上吗”?你会怎么计算?中等
  • 生产速率:每秒新增消息数。
  • 消费速率:每秒消费完成数(成功 + 可容忍失败处理)。
  • 结论:如果消费速率 < 生产速率,积压只会越来越大;必须先降低生产(限流/降级)或提升消费能力。
💡 面试表达:我会把堆积问题转化成一个吞吐模型,然后给出可以量化的恢复时间预估。
3. 快速恢复:你有哪些“止血手段”?困难
  • 扩容消费者:增加实例数(受限于分区/队列并发度)。
  • 提高并发:线程池并发、批量拉取/批处理(注意下游承受能力)。
  • 隔离慢消息:失败/超时消息进入重试队列或死信队列,主消费链路先恢复。
  • 降级业务:非核心消息延后处理或丢弃(需要业务允许)。
⚠️ 注意:盲目提高并发可能把 DB/Redis 打爆,必须同步做下游保护(限流/熔断/隔离)。
4. 什么是重试风暴?怎么避免?困难

重试风暴指大量消息失败后立即/高频重试,导致消费者持续失败、吞吐下降,堆积更严重。

  • 退避重试:指数退避 + 抖动,避免同一时间重试。
  • 区分可重试/不可重试:参数错误/业务拒绝应直接进死信,不要无限重试。
  • 隔离重试通道:主消费链路与重试链路隔离资源。
  • 幂等与去重:保证重试不会造成重复扣款/重复发券。
5. 长期治理你会怎么做?中等
  • 监控指标:lag、积压量、消费耗时、失败率、重试次数、死信量。
  • 容量规划:按峰值预估分区数/并发度,上游削峰(缓存/队列/异步)。
  • 热点治理:按 key 分片、避免单分区热点。
  • 故障演练:模拟下游不可用,验证重试策略不会雪崩。