没有 DLQ 的 workflow,失败任务会污染主队列;只有 DLQ 但没有分诊规则,失败任务会永久堆积。真正可运营的系统需要“隔离 + 分诊 + 恢复”闭环。
关键问题不是“有没有 DLQ”,而是“DLQ 里的任务能不能被可控地救回来”。
DLQ 设计目标
- 隔离不可自动恢复任务,避免污染主队列
- 保留恢复所需证据(输入、版本、失败点)
- 提供受控回放入口与策略闸门
DLQ 的核心不是存储,而是恢复治理。
入队标准必须结构化
建议至少记录以下字段:
- failureType
- failedNode
- runVersion
- dependencyStatus
- retryHistory
- sideEffectRisk
没有结构化入队原因,后续分诊只能靠人工读日志。
分诊分层
| 类别 | 处理方式 | owner |
|---|---|---|
| 数据问题 | 补充字段后重放 | 业务/运营 |
| 依赖问题 | 等依赖恢复后重试 | 平台运维 |
| 策略问题 | 规则修正后批量回放 | 治理团队 |
| 代码缺陷 | 修复版本后灰度回放 | 工程团队 |
把不同问题混在同一重试策略里,几乎必然触发二次故障。
回放闸门设计
回放前建议强制通过三道检查:
- 前置条件检查:依赖状态、版本可用性。
- 风险检查:是否包含不可逆副作用。
- 负载检查:当前队列与并发是否允许。
没有闸门的批量回放,本质是“带规模的盲试错”。
失败案例:DLQ 批量重放触发风暴
某团队在外部依赖尚未恢复时批量回放 DLQ,结果同类失败再次挤爆队列,甚至影响正常新任务。
修复动作:
- 回放前引入依赖健康检查。
- 批量回放采用分批与并发限流。
- 高风险任务先走小样本回放,再逐级放量。
恢复稳定后,DLQ 不再是“故障放大器”。
看板指标建议
- DLQ backlog 总量与老化分布
- 可回放任务比例
- 回放成功率
- 回放后二次入队率
二次入队率持续高,通常说明分诊规则或回放闸门设计有缺陷。
DLQ 记录应该包含哪些字段
| 字段 | 目的 |
|---|---|
| originalRunId | 关联原始任务 |
| failedNodeId | 定位失败节点 |
| failureType | 分诊入口 |
| recoverability | automatic / manual / blocked |
| replayPolicy | 是否允许回放、如何限流 |
| evidencePackId | 人工处理所需证据 |
如果 DLQ 只存一段错误文本,它就不是恢复队列,只是失败日志。
运营节奏:每天清理,不是月底考古
建议建立固定节奏:
- 每日:处理 aging 超过阈值的任务。
- 每周:统计失败类型趋势,修复高频类别。
- 每月:清理长期 blocked 任务并做策略复盘。
DLQ 是运营系统的一部分,不是工程团队偶尔想起来才看的角落。
三个反模式
- 无限自动重放:把 DLQ 变成重试风暴入口。
- 全部人工处理:吞吐崩溃,且无法积累恢复规则。
- 只看数量不看老化:backlog 不大也可能有高风险任务长期卡住。
真正成熟的 DLQ,看的是“恢复质量”,不只是“队列是否清空”。
Checklist
- DLQ 入队原因结构化
- 每类失败有明确分诊 owner
- 回放前执行前置条件与风险检查
- 批量回放支持并发限流与灰度放量
- 老化任务有升级与人工介入机制
延伸阅读:


