RabbitMQ死信队列

一、什么是死信队列

消息无法被正常消费,被 broker 判定为失效消息 ,不会继续留在原队列等待重试,转而投递到预先绑定的队列,这个专门接收失效消息的队列就是死信队列

消息变成死信的三种核心场景

  1. 消费者拒绝消息
    • basicNack / basicReject,并且设置 requeue=false(不重新放回原队列); 手动业务异常,主动拒收消息,不重试。
  2. 消息超时(TTL 过期)
    • 消息本身设置过期时间;
    • 队列设置全局消息过期时间; 消息一直未被消费,超时自动沦为死信。
  3. 队列达到最大长度 队列堆积消息数量超过 x-max-length 上限,队尾多余消息被丢弃转入死信。

死信队列不是特殊类型队列,只是普通队列,依靠**死信交换机 DLX(Dead Letter Exchange)**实现路由转发。

二、核心组件:DLX 死信交换机

  1. 原业务队列 配置两个参数:
    • x-dead-letter-exchange:指定死信交换机名称;
    • x-dead-letter-routing-key:死信转发时使用的路由键(可选,默认沿用原消息 routingKey);
  2. 消息判定为死信后,RabbitMQ 会自动将这条消息重新发送到 DLX,DLX 根据路由键投递到绑定的死信队列。

整体流转链路:

复制代码
生产者 → 普通交换机 → 业务队列 → 消费失败/超时/队列满
→ broker自动转发 → DLX死信交换机 → 死信队列DLQ

三、常用配置方式

方式 1:创建业务队列时绑定 DLX(最常用)

1)界面管理端配置

创建队列时添加 Arguments:

参数键 说明
x-dead-letter-exchange 填写提前建好的死信交换机名称
x-dead-letter-routing-key 死信路由键,自定义
x-message-ttl 队列全局消息过期时间,单位 ms
x-max-length 队列最大消息条数
2)Java SpringBoot 代码示例
复制代码
// 1.声明死信交换机
@Bean
public DirectExchange deadLetterExchange() {
    return ExchangeBuilder.directExchange("dlx.exchange").durable(true).build();
}

// 2.声明死信队列
@Bean
public Queue deadLetterQueue() {
    return QueueBuilder.durable("dlq.queue").build();
}

// 3.绑定死信交换机与死信队列
@Bean
public Binding deadLetterBinding() {
    return BindingBuilder.bind(deadLetterQueue())
            .to(deadLetterExchange())
            .with("dl.routing.key");
}

// 4.业务队列绑定死信交换机配置
@Bean
public Queue businessQueue() {
    return QueueBuilder.durable("business.queue")
            // 指定死信交换机
            .withArgument("x-dead-letter-exchange", "dlx.exchange")
            // 指定死信路由key
            .withArgument("x-dead-letter-routing-key", "dl.routing.key")
            // 可选:消息30秒超时未消费则进死信
            .withArgument("x-message-ttl", 30000)
            .build();
}

四、典型业务使用场景

1. 消费失败兜底处理

业务处理异常(数据库异常、第三方接口报错),不无限重试:

  • 消费者捕获异常,执行 nack(requeue=false)
  • 消息进入死信队列,人工排查问题后重新投递。

2. 延迟队列(经典实现方案)

利用 TTL + 死信间接实现延迟:

  1. 消息先进入设置 TTL 的临时队列,无消费者;
  2. 消息超时自动转入 DLX,路由到目标业务队列;
  3. 消费者监听目标队列,达到定时消费效果。

局限:同一队列 TTL 必须一致,高精度延迟建议使用 RabbitMQ 延迟插件。

3. 防止消息无限堆积

限制业务队列最大消息数,流量突增打爆队列时溢出消息进入死信,避免服务雪崩。

五、死信队列标准运维方案

  1. 独立消费者监听死信队列 专门消费死信消息,记录日志、入库标记异常订单 / 任务,发送告警(钉钉 / 邮件);
  2. 死信重试策略
  • 方案 A:人工修复问题后,将死信消息重新发送至原业务交换机;
  • 方案 B:延时重试:死信接收后暂存 Redis,间隔一段时间重新投递,多次失败后永久归档;
  1. 死信消息留存 死信队列尽量不自动删除,保留数据用于问题溯源,定期归档清理。

六、容易踩坑的常见问题

  1. nack requeue=true 不会进死信 消息只是重回原队列头部,反复重试,极易死循环堆积,业务异常务必 requeue=false
  2. 死信交换机必须提前创建 如果业务队列配置的 DLX 不存在,死信消息会直接被丢弃;
  3. 死信消息携带原有属性 原消息的 headers、body、routingKey 都会保留,同时新增死信原因标识;
  4. 队列 TTL 和消息 TTL 优先级 消息发送时设置的expiration优先级 > 队列配置的x-message-ttl

七、简易工作流程示例

  1. 生产者发送消息到 business.exchangebusiness.queue
  2. 消费者处理报错,channel.basicNack(deliveryTag, false, false)
  3. RabbitMQ 检测到拒收且不重回队列,转发消息到 dlx.exchange
  4. DLX 根据路由键把消息投递至 dlq.queue
  5. 运维 / 专门消费者监听 dlq.queue,打印日志、触发告警,排查问题后重投。
相关推荐
ZGi.ai2 分钟前
知识库权限变了,怎样避免答错?
agent·权限管理·知识库·工作流·zgi·客服运营
大模型真好玩24 分钟前
DeepSeek Harness 入门很简单(四)——DeepSeek Harness接入插件
人工智能·agent·deepseek
掰头战士38 分钟前
MCP、Skill、Plugin,都是给agent拓展能力,到底有何区别?
typescript·llm·agent
wzdark1 小时前
基于链表的内存池设计与内存复用机制4
java·数据结构·链表
cnkeysky1 小时前
idea 中的 maven 项目重新加载子模块
java·idea
Escalating_xu1 小时前
【System V 信号量】从 P/V 原语到 Builder 封装:写出可控、可清理的进程互斥组件
java·linux·开发语言·jvm
今天AI了吗2 小时前
什么是 AI Agent?它与直接调用大模型 API 有何区别
java·网络·人工智能·架构·java-ee
隐退山林2 小时前
JavaEE进阶:SpringAOP
java·java-ee
Wang's Blog2 小时前
Java框架快速入门: Spring Security+OAuth2之方法级安全注解
java·安全·spring
嘟嘟嘟95272 小时前
AI Agent 的边缘困境
人工智能·架构·agent