死信队列(Dead-Letter Queue,DLQ)就是消息的"太平间" ------
正常队列里"死掉"的消息,统一拉到这儿来,方便后续排查、重试或人工干预,而不是直接扔掉。
一、消息是怎么"死"的
-
重试次数用尽
消费失败,系统重投 3~5 次仍报错 → 认为"救不活"。
-
TTL 过期
消息在队列里待的时间超过设定的存活期(Time-To-Live)。
-
队列长度超限
队列满,最早的消息被"挤"出来。
-
手动否定
业务代码明确
basic.reject/basic.nack且requeue=false。
二、死信后的流程(以 RabbitMQ 为例)
┌------------ 正常业务队列 ------------┐
│ │
│ x-dead-letter-exchange = "dlx.exchange" │
│ x-dead-letter-routing-key = "dlq.key" │
▼ │
消费失败/过期/超限 → 消息被 reject/nack → RabbitMQ 自动转发 → 死信队列(DLQ)
│
▼
死信消费者(日志、告警、人工补单)
三、代码片段(RabbitMQ)
java
// 1. 声明正常队列时绑定死信参数
Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", "dlx.exchange");
args.put("x-dead-letter-routing-key", "dlq.key");
args.put("x-message-ttl", 30000); // 30 秒没消费就过期进 DLQ
channel.queueDeclare("business.queue", true, false, false, args);
// 2. 声明死信交换机和队列
channel.exchangeDeclare("dlx.exchange", "direct");
channel.queueDeclare("dead.queue", true, false, false, null);
channel.queueBind("dead.queue", "dlx.exchange", "dlq.key");
四、Kafka 里的 DLQ
Kafka 没有原生 DLQ,客户端自己实现 :
spring-kafka 的 SeekToCurrentErrorHandler
重试 N 次后把消息发到名为 xxx.DLT(Dead-Letter Topic)的 topic,效果一样。
五、死信队列用来干啥
- 记录+报警:消息进 DLQ 立刻发钉钉/邮件。
- 人工修复:运营后台拉取 DLQ 内容,补发或修正数据。
- 二次重试:DLQ 消费者等系统空闲再把消息写回原队列。
一句话:
死信队列 = 正常队列的" ICU 病房" ,专门收容那些救不活 的消息,让它们死得明白、死得有价值,而不是无声无息地消失。