RabbitMQ生产者异步回调防消息丢失需三步:一设publisher-confirm-type为correlated;二注册ConfirmCallback并传CorrelationData实现精准失败定位与补偿;三启用ReturnCallback(配publisher-returns:true和mandatory:true)捕获未路由消息。

生产者异步回调是 RabbitMQ 防消息丢失的第一道防线,核心在于让生产者“不盲发”,而是等 MQ 的确认反馈再决定后续动作。配置本身不复杂,但关键细节容易漏掉,直接影响可靠性。
开启异步确认模式(publisher-confirm-type)
必须设为 correlated,这是唯一支持异步回调且能携带消息上下文的模式。simple 模式只能同步阻塞等待,correlated 才允许你绑定唯一 ID 并在回调中精准定位哪条消息失败。
- application.yml 中配置:
spring:rabbitmq:publisher-confirm-type: correlated - 不要用
simple或留空,默认值不保证异步行为 - 该配置作用于整个 RabbitTemplate 实例,全局生效
注册 ConfirmCallback 处理投递结果
回调函数负责接收 MQ 返回的 ack/nack,是重试或落库的决策入口。重点不是写个空实现,而是做两件事:区分成功与失败、保留可追溯的上下文。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 发送时必须传入 CorrelationData,里面包含唯一 ID(如 UUID),用于关联原始消息和回调结果
- 回调中判断 ack == false 时,立即记录日志并触发补偿逻辑(如存本地表、发告警)
- 避免在回调里直接重发——可能造成重复;推荐先持久化失败记录,由独立定时任务驱动重试
启用 ReturnCallback 拦截未路由消息
ConfirmCallback 只管“是否到交换机”,而消息到了交换机却找不到队列(比如 routingKey 写错、队列被删),默认就静默丢弃。ReturnCallback 就是专治这种“半路失踪”。
- 配置两项缺一不可:
spring:rabbitmq:publisher-returns: truespring:rabbitmq:template:mandatory: true - mandatory=true 是开关,没有它,即使开了 publisher-returns 也不会触发回调
- 回调中拿到 ReturnedMessage,可提取 exchange、routingKey、消息体,用于诊断或人工介入
配套动作不能少
光有回调不够,还要支撑它真正起作用:
- 每条消息配唯一 CorrelationData ID,方便追踪和去重
- 失败消息别只打日志,至少落库或 Redis,否则重启后无从恢复
- 避免在 ConfirmCallback 里做耗时操作(如远程调用),防止阻塞回调线程池
- 测试时主动模拟失败场景:关掉 RabbitMQ、输错 exchange 名,验证回调是否如期触发

















