← 返回题目列表

死信队列如何设计和处理?

高频 中等 第 7 / 26 题 更新于 2026/10/06
消息队列死信队列补偿重放
学习 AI 实战项目

简化版

死信队列用于隔离超过重试上限、不可解析或业务永久失败的消息,避免毒消息阻塞主消费。死信必须保留原消息、失败原因、消费组、尝试次数和追踪信息,并配告警、修复、审批重放和最终归档,不能成为无人管理的垃圾桶。

详细版

先把错误分为瞬时、永久和未知:瞬时错误退避重试,参数/Schema 错误尽快死信,结果未知先查询事实。进入 DLQ 时使用稳定 eventId,并把原 payload 与诊断元数据可靠写入;敏感字段按权限保护。

修复后用独立 replay 流程小批重放,消费者保持幂等,控制速率并记录新旧消息关系。监控进入率、最老死信年龄、原因分布、待处理量和重放结果;设置 owner 与处理 SLO,永久无法恢复的消息需要审批归档或丢弃。

完整版教学

一、DLQ 的职责边界

DLQ 是失败隔离区与调查队列,不是成功保证。它让主分区继续前进,并保存失败证据供修复;若没人处理,业务仍然处于未完成状态。

记忆钩子:死信不是“死掉就算了”,而是从自动路径转入受控恢复路径。

二、哪些错误应进入

错误是否重试典型处理
短暂网络错误是退避重试
参数非法否直接 DLQ
Schema 不兼容修复后DLQ+转换
下游超时未知先查询再决定

固定次数并非唯一标准,还应受总时间预算和业务过期时间限制。

三、死信信封包含什么

保留 eventId、原 Topic/partition/offset、key、payload 或安全引用、Schema 版本、消费者版本、错误类型、堆栈摘要、首次/最后失败时间、attempt、traceId。不要只保存一段异常文本,否则无法可靠重放。

{"eventId":"E9","source":"orders-3@1024","reason":"SCHEMA","attempt":4}

敏感 payload 加密并限制访问,日志只保留脱敏摘要。

死信记录还应固定原始字节或不可变对象引用,避免后续 Schema 转换覆盖事故现场,使重放输入与调查证据不一致。

四、避免毒消息阻塞顺序

严格同 key 顺序场景中跳过失败消息,后续事件可能建立在缺失状态上;一直重试又会阻塞分区。可暂停该 key 并把其他 key 路由到独立处理,或把失败及后续同 key 事件一起隔离。必须明确顺序边界。

例如订单 Created 失败却先处理 Shipped,会得到非法状态,不能只以“主队列畅通”为目标。

五、安全重放流程

先修复代码或数据,选择少量死信在影子环境验证,再按原因和时间窗口审批重放。重放保留原 eventId 作为业务幂等身份,另加 replayId 标识本次重放尝试,限速进入独立 Topic;观察成功、重复命中与下游负载后逐步扩大。

直接把 DLQ 全量复制回原 Topic 会再次污染主流量,并可能形成“主队列—DLQ”无限循环。

六、生命周期与责任人

每类 DLQ 必须有 owner、告警阈值、处理 SLO、保留期和 Runbook。保留到期前,未解决消息应归档到可审计存储;丢弃需要业务审批和影响清单。修复后做业务对账,而不只看重放 ACK。

监控 dlq ingress、backlog、oldest age、reason、replay success 和循环次数。突然出现新原因应立即告警。

归档与删除策略要覆盖最长排障和合规窗口;只延长 DLQ Topic 保留期而不核算磁盘,可能在事故期间触发更早的容量清理。

七、常见误区与追问

  • 误区:进入 DLQ 就算处理完成。 业务仍未收敛。
  • 误区:所有失败都重试固定三次。 永久错误只会浪费资源。
  • 误区:修复后全量回灌原 Topic。 可能冲击下游并形成循环。
  • 误区:死信只保存原 payload。 缺少来源和失败上下文难以恢复。
  • 追问:顺序消息如何死信? 隔离同 key 后续事件或采用业务状态补偿。
  • 追问:重放如何防重复? 稳定 eventId、幂等状态机和唯一约束。
  • 追问:死信可以删除吗? 过保留期可审批归档/丢弃,并保留审计与对账。

八、加强记忆

DLQ 的闭环是“分类错误—保存证据—隔离影响—修复验证—限速重放—业务对账”。它保护主消费但不替业务成功;只有具备 owner、SLO、幂等和审计,死信队列才是恢复机制而不是失败仓库。