消息重试要有出口
消息重试要有出口
消息失败后直接重试,是最容易想到的方案。但如果失败原因一直存在,无限重试只会让队列堆积、日志刷屏、下游压力增加。重试机制必须有出口。
先区分失败类型
消费失败可能是临时网络问题,也可能是参数错误、业务状态不允许、下游数据缺失。临时问题适合重试,确定性的业务错误则不应该一直重试。
所以消费端不能只 catch 异常后统一抛出。它需要尽量识别错误类型,把可恢复和不可恢复的问题分开处理。
重试要配合幂等
只要有重试,就必须考虑幂等。消费者可能在业务动作已经完成后,因为响应失败或提交失败被再次触发。如果没有幂等保护,重试会变成重复执行。
我会优先用业务唯一标识和状态判断保护消费逻辑,确保同一条业务事件重复到达时结果仍然稳定。
出口要能被看见
失败消息进入死信队列或异常表后,事情并没有结束。还需要告警、查询页面、人工处理入口和补偿记录。否则消息只是从主队列挪到了另一个没人看的地方。
真正可维护的消息系统,应该能回答哪些消息失败了、为什么失败、是否处理过、处理结果是什么。
复盘
消息重试的目的不是让系统看起来很努力,而是提高临时故障下的恢复能力。重试要有次数、间隔、幂等、死信和告警,形成闭环才算完整。
参考
- RabbitMQ 死信文档:https://www.rabbitmq.com/docs/dlx
- Kafka 消费者文档:https://kafka.apache.org/documentation/#consumerconfigs