一条坏消息不应阻塞整个流
消费者按顺序处理消息。一条格式错误的消息失败、重试、再次失败,并阻塞后面所有消息。死信队列在达到重试上限或遇到不可重试错误后把消息移走。消费者继续运行,运维人员可以带着错误上下文检查被停放的消息。
{
"RedrivePolicy": {
"deadLetterTargetArn": "arn:aws:sqs:region:account:orders-dlq",
"maxReceiveCount": 5
}
}
示例是 SQS 的重驱动策略。RabbitMQ 使用死信交换机;Kafka 常用独立的 DLQ topic,并附带原 topic、partition、offset 和错误头。机制不同,策略相同:有界重试、保留上下文、保持可见。
区分失败类型
不是所有失败都该进死信队列。超时或暂时不可用的依赖应使用指数退避加抖动重试。模式不匹配、非法负载或授权失败,在生产方或数据修复前都是永久错误,重试只会浪费容量。有些系统把重试队列和死信队列分开:瞬时失败获得延迟,永久失败立即停放。
要保留原始消息、异常、消费者版本和尝试次数。没有这些上下文,死信队列只是一堆难以理解的负载。对队列深度和消息年龄告警;即使主链路健康,持续增长的死信队列也是运维信号。
谨慎重放
重放是一次新的生产事件。消费者必须幂等,因为原投递可能已部分成功。乱序重放死信队列可能丢失顺序,需确认消费者是否依赖序列。模式或代码变化后,先重放到预发消费者。记录谁在何时重放了什么。
何时使用
当有界重试后消息仍可能无法处理,而阻塞进度不可接受时,使用死信队列。优点是隔离与诊断;代价是多一个需要监控、保护和清理的队列。与无限重试相比,死信队列让失败可见;与直接丢弃相比,它保留了恢复机会。