主题
概念卡片:RabbitMQ 消息可靠性
一句话机制:消息从发送到消费要经历「Producer → Exchange → Queue → Consumer」多跳,每一跳都可能丢消息;可靠性靠四件事兜底——生产者 confirm/return 确认、MQ 持久化、消费者 ack、失败重试 + 死信,再配合幂等防重复消费。
消息丢失的三个环节与对策
| 环节 | 丢失原因 | 对策 |
|---|---|---|
| 发送时 | 消息未达 Exchange / 未达 Queue | 生产者确认:confirm(到 Exchange)/ return(到 Queue 失败退回) |
| MQ 宕机 | Queue 未持久化 | 持久化:queue + message 都设持久化 |
| 消费时 | 消费者收到后未处理就宕机 | 消费者 ack:处理成功才 ack,否则重试 |
可靠性四件套
yaml
spring:
rabbitmq:
publisher-confirm-type: correlated # 生产者确认(producer→exchange)
publisher-returns: true # 退回模式(exchange→queue 失败)
listener:
simple:
acknowledge-mode: auto # 消费者自动 ack(处理成功后确认)
retry:
enabled: true # 失败重试
max-attempts: 3重试仍失败 → 投递到死信交换机(Dead Letter Exchange),由
MessageRecoverer转人工处理,避免无限重试。
三个进阶难题
| 难题 | 解法 |
|---|---|
| 重复消费 | 幂等:业务侧唯一 ID(如订单号)去重,或用消息去重表 |
| 顺序性 | 同一业务 key 的消息路由到同一个队列(单消费者消费),或多消费者用「分区」保证局部有序 |
| 消息积压 | 临时扩容消费者、批量消费、降级非核心消息,积压严重时直接扩容消费者实例 |
不变量(必须成立的约束)
- 可靠性三件套(confirm + 持久化 + ack)缺一环都会丢消息,必须全部开启。
- ack 是「处理成功才确认」,配
auto模式由 Spring 在方法正常返回后 ack,异常则不 ack 触发重试。 - 消息队列本身不保证顺序,要顺序必须「同 key 进同队列 + 单消费者」。
- 幂等是消费端的责任(RabbitMQ 不保证 exactly-once),靠业务唯一 ID 去重。
踩坑案例
- 现象:消费者处理失败,消息被无限重试打爆日志。 原因:没配死信交换机/重试上限。解决:配
retry.max-attempts+ 死信队列,重试耗尽后转人工。
常见误解
- 以为「消息不丢」只靠持久化 → 持久化只防「MQ 宕机丢失」,发送丢失靠 confirm、消费丢失靠 ack,是三件事。
- 以为 MQ 保证消息不重复 → MQ 是「至少一次投递」,可能重复,去重靠消费端幂等。
关联
- 总览:消息队列技术栈总览
- 工作模式:概念卡片:RabbitMQ工作模式
- 源:
B40-资源/语雀-Leo的知识库/微服务/03_RabbitMQ/_5_消息的可靠性投递+ 面试题 10 篇