Skip to content

死信与延迟

消费重试、死信队列、延迟队列实现。

Updated View as Markdown
For humans

死信与延迟

消费失败的兜底机制(死信)和定时触发机制(延迟),是 MQ 生产实践的两个必备组件。

消费重试

重试耗尽进死信

重试方式 机制 适用
消费者内重试 捕获异常重试 N 次 简单场景(限流/瞬时故障)
延迟重投 失败消息延迟后重新消费 下游恢复需要时间
死信队列 重试耗尽转人工处理 系统性错误(数据问题)

重试要有上限:无限重试 = 队列阻塞 + 下游持续被打。

死信队列(DLQ)

  • 死信:重试耗尽仍失败的消息,转入专用队列
  • 价值:隔离问题消息,不阻塞主队列;可监控积压、人工修复、重放
  • 设计要点:
要点 说明
死信带原因 记录失败原因(错误信息、重试次数)
监控告警 DLQ 积压 = 系统性 bug 的信号
重放机制 修复后能重新投递(工具 + 人工审核)
分区隔离 不同业务不同 DLQ

延迟队列

延迟消息 = 到了指定时间才可见(下单 30 分钟未支付自动取消)。

实现 机制 精度 复杂度
RabbitMQ 延迟插件 x-delayed-message 交换机 秒级
定时任务扫表 数据库状态 + 轮询 分钟级 低(量小)
Redis zset 到期时间作分数,轮询取到期任务 秒级
Kafka 分层时间轮 时间轮 + 延迟索引 秒级 高(Kafka 2.x+)

Redis zset 方案(高频考点):

ZADD delay_queue <到期时间戳> <任务>
轮询: ZRANGEBYSCORE delay_queue 0 <now> → ZREM 取出 → 处理
(取出要 ZREM 删除, 否则下次轮询重复取出)

面试追问

  1. 重试什么时候放弃? 重试 N 次(指数退避)仍失败进死信。无限重试是灾难
  2. 死信队列的价值? 隔离问题消息不阻塞主队列 + 监控积压定位系统问题 + 人工修复重放
  3. 延迟队列怎么做? RabbitMQ 延迟插件、Redis zset(时间戳作分数)、时间轮。按精度和量级选
  4. 死信和延迟的区别? 死信是失败兜底(转入人工),延迟是定时触发(到时可见)
  5. DLQ 积压说明什么? 系统性 bug(数据格式、逻辑错误),要告警和人工介入,不是调大重试能解决的
Navigation

Type to search…

↑↓ navigate↵ selectEsc close