现在瞬时失败(传输、5xx)恰好重新入队一次(message.redelivered 防止热循环)
热循环是什么?
文章目录
- 热循环(Hot Loop / Hot Cycling)
- 一句话定义
- 用第 3 条的场景举例
- 为什么危险
- 文中怎么防止热循环
- 类比
热循环(Hot Loop / Hot Cycling)
一句话定义
热循环是指一条有问题的消息被反复消费、反复失败、反复重新入队,形成一个停不下来的死循环,像发动机空转一样快速"烧"资源。
用第 3 条的场景举例
消息队列里有一条"毒消息"(比如数据格式错了) │ ▼ 消费者拿到消息 → upsert 失败(数据校验不通过,4xx 错误) │ ▼ 消费者没有 ACK → 消息队列认为"没处理完",把消息重新放回队列 │ ▼ 消费者立刻又拿到同一条消息 → 又失败 │ ▼ 又没 ACK → 又放回队列 → 又消费 → 又失败 → 又放回... │ ▼ ♻️ 无限循环,每秒可能重复几十上百次这就是热循环——消息在队列和消费者之间飞速弹跳,永远处理不成功,但永远在重试。
为什么危险
| 危害 | 说明 |
|---|---|
| CPU / 资源空转 | 消费者不停处理同一条注定失败的消息,浪费算力 |
| 队列堵塞 | 这条消息占住消费者,正常的消息排不上队 |
| 日志洪泛 | 每次失败都记日志,瞬间产生海量无用日志 |
| 指标失真 | 失败次数飙升,监控告警被淹没 |
| 级联故障 | 如果失败涉及外部调用(如数据库),会把下游也拖垮 |
文中怎么防止热循环
瞬时失败恰好重新入队一次(
message.redelivered防止热循环)
第 1 次消费 → 失败(网络抖动 5xx) │ ▼ 检查 message.redelivered == false ← 还没重试过 │ ▼ 重新入队(NACK),允许重试一次 │ ▼ 第 2 次消费 → 又失败 │ ▼ 检查 message.redelivered == true ← 已经重试过了! │ ▼ 不再重新入队,走毒消息流程:记指标 + 丢弃 │ ✅ 循环终止message.redelivered是消息队列(如 RabbitMQ)提供的一个标志位:
- false= 第一次被消费 → 可以给一次重试机会
- true= 已经被重新投递过了 → 不再重试,直接丢弃
这样就把重试次数硬限制为 1 次,彻底打断了热循环。
类比
想象一台自动售货机:
- 正常情况:投币 → 出货 → 完成 ✅
- 热循环:投币 → 卡住了 → 机器退币 → 你立刻又投同一枚币 → 又卡住 → 又退币 → 又投… 你俩都停不下来了 🔄
- 防热循环:机器说"同一枚币只允许投两次,第二次再卡住我就吞币报修" 🛑