一句话定义:死信队列(Dead Letter Queue,DLQ)是消息系统里专门收留“怎么处理都处理不成功”的消息的兜底队列——它不是垃圾桶,而是一个待处理的隔离区。
先说它解决什么问题。异步系统里,生产者把任务写进队列,消费者从队列里取出来处理。理想情况下一次就成,但现实里有网络抖动、下游服务临时挂了、某条数据本身格式就不对。于是系统会重试(retry)。重试是对付瞬时故障的,可如果这条消息注定处理不了——比如文件损坏、字段缺失、内容超出了模型能接受的长度——重试一百次也是白费,还会占着队列、拖慢后面的正常消息。
所以需要一个上限:重试到第 N 次仍然失败,就判定为“死信”(dead letter),把它挪到另一个队列里去。这个队列就是死信队列。
打个快递的比方:快递员送货,第一次没人签收,会再送一次、两次,最多三次;三次都送不到,包裹不会继续每天往同一个地址跑,也不会直接销毁,而是退回“问题件仓库”等人查地址、打电话、重新派送。重试队列是“明天再送一次”,死信队列是“先退回仓库,别堵在车上”。
哪些情况会进死信队列?常见的有:重试次数达到上限;消息过期(TTL 到期);队列满了被拒绝;消费者明确拒收且要求不重新入队。
它和相邻概念容易混,区别大致如下:
| 概念 | 消息状态 | 会自动再处理吗 | 主要用途 |
|---|---|---|---|
| 主队列 | 正常待处理 | 是 | 承载正常流量 |
| 重试队列 | 暂时失败,还有希望 | 是,延迟后再试 | 吸收网络抖动等瞬时故障 |
| 死信队列 | 已判定处理失败 | 默认不会 | 留证据、人工排查、批量重放 |
| 普通日志 | 只是记录,不是消息 | 不适用 | 排查与审计 |
和日志最大的不同是:日志是给人看的文本,死信队列里躺的是消息本体,理论上可以修好问题后重新投回主队列,这叫重放(replay)。
对 AI 从业者来说,这个机制非常日常。RAG 的文档批量入库、离线批量 embedding、调用大模型的长任务、数据清洗流水线,几乎都是异步的。某份 PDF 解析失败、某段文本超长、某个请求连续超时,重试几次后就会落进死信队列。几条实践建议:
1. 必须配告警。没人看的死信队列等于数字垃圾场,事后才发现丢了几万条。
2. 入队时带上上下文:失败原因、重试次数、原始时间戳、原始消息体。只存一个 ID,捞回来也没法修。
3. 提前设计重放路径,并且保证处理逻辑幂等(idempotent),否则重放会写出重复数据。
4. 设置保留期和容量上限,避免无限膨胀。
对普通职场人:你提交的表单一直显示“处理中”、上传的文件迟迟没变成“已完成”,背后很可能就是那条消息已经进了死信队列,在等开发或运维把它捞出来修。所以“卡住了”通常不等于“丢了”。
最后提醒一句:不同消息中间件对死信队列的叫法和触发条件并不完全一致,有的叫 dead letter channel,有的叫未投递消息。具体行为请以你所用产品的官方文档为准。
