🧩 场景题题干(面试官常用表述)
现象:Kafka/RabbitMQ/RocketMQ 堆积严重,延迟越来越大。
你怎么判断是生产太快还是消费太慢?
怎么快速恢复?怎么避免重试风暴?
💡 一句话思路:先算“积压能否被追上”(消费能力 vs 生产速度),再做短期扩容/并发提升/批处理,最后用限流、死信队列、幂等与降级治理重试风暴。
📚 学习正文:MQ 堆积如何定位到“具体瓶颈/具体消费者/具体下游”?
1) 先止血:让积压不再继续扩大
止血目标:让 消费速率 ≥ 生产速率
手段:降低生产(限流/降级) + 提升消费(扩容/并发/批处理) + 隔离失败/慢消息(死信/重试隔离)
2) 先把问题量化:追得上吗?需要多久恢复?
关键公式:
恢复时间 ≈ 当前积压量 / (消费速率 - 生产速率)
如果 消费速率 ≤ 生产速率:积压只会越来越大,必须先控生产或扩分区/扩并发。
3) 证据链:定位“慢在 MQ 还是慢在下游”
- 消费耗时分布:单条消息处理耗时是否飙升?
- 失败率与重试:失败导致重试风暴会直接把吞吐打下来。
- 下游依赖:DB/Redis/第三方慢导致消费者线程池排队。
4) 快速恢复的工程手段
- 扩容消费者:实例数上去(受限于分区/队列并发度)。
- 提高并发:线程池并发/批量消费,但要保护下游。
- 隔离慢消息:把失败/超时消息移到重试队列或死信队列,主链路先恢复。
- 削峰填谷:生产侧做缓冲/队列,避免把峰值直接打到消费端。
5) 如何避免重试风暴(最容易把系统拖垮)
退避重试(指数退避+抖动)
区分可重试/不可重试(业务拒绝直接死信)
重试链路与主消费链路隔离资源
消费幂等 + 业务唯一约束兜底
6) 长期治理
监控:lag/积压量/失败率/重试次数/死信量
容量:分区数与并发度规划
演练:下游不可用/重试风暴演练
治理:热点 key 分片,避免单分区热点