RabbitMQ
RabbitMQ 的后端工程主笔记:从 Exchange/Queue/Binding、ACK/Confirm、Prefetch、DLQ/Retry,到 Quorum Queue、路由模型、高可用和与 Kafka 的选型边界。
[!info] related notes
RabbitMQ
[!abstract] 一句话定位 RabbitMQ 是以 Exchange、Queue、Binding 和 Consumer Acknowledgement 为核心的消息 Broker,擅长把消息可靠地路由到目标队列,再交给一个或一组 Worker 处理。它比 Kafka 更贴近 Work Queue、Command、复杂路由和 Retry / DLQ 场景。
核心数据模型
Publisher
↓ publish(exchange, routing key)
Exchange
↓ binding rules
Queue
↓ delivery
Consumer
↓ process
ACK / NACK
| 对象 | 职责 |
|---|---|
| Publisher | 发布消息 |
| Exchange | 根据类型、Routing Key 和 Binding 做路由 |
| Queue | 保存待消费消息 |
| Binding | 描述 Exchange 到 Queue 的路由关系 |
| Consumer | 接收并处理 Queue 中的消息 |
| Virtual Host | 隔离 Exchange、Queue、Binding 与权限命名空间 |
Exchange 类型
| 类型 | 路由方式 | 典型场景 |
|---|---|---|
| Direct | Routing Key 精确匹配 | 明确命令或分类 |
| Topic | * / # 模式匹配 | 分层业务事件 |
| Fanout | 广播到所有绑定 Queue | 通知多个独立下游 |
| Headers | 根据 Header 匹配 | 少量特殊路由需求 |
[!tip] 广播的对象是 Queue 多个 Consumer 消费同一个 Queue 时通常是竞争消费;要让多个业务都收到一份,应为它们建立不同 Queue,并分别绑定到 Exchange。
可靠发布:Publisher Confirm
“客户端没有报错地写入 Socket”不代表 Broker 已经接管消息。Publisher Confirm 让 Broker 向 Publisher 确认该消息已达到相应 Queue 类型定义的安全点。
publish
→ route to queue(s)
→ persist / replicate as required
→ broker confirm
还要处理 unroutable message:
- Exchange 不存在通常导致 Channel 错误;
- 没有匹配 Queue 时,可使用
mandatory+ return handler 或 alternate exchange; - Confirm 与“消息是否被业务 Consumer 成功处理”无关。
可靠消费:Manual ACK
重要业务通常按以下顺序:
receive delivery
→ validate / process
→ commit business effect
→ ACK
如果业务处理成功后、ACK 前崩溃,消息可能重新投递。因此常见组合是:
At-least-once + Idempotent Consumer
Auto ACK 的风险
Auto ACK 更接近“Broker 发出后就认为完成”。Consumer 真正处理前崩溃时,消息可能丢失。只有明确允许这种风险时才使用。
Prefetch 与 Backpressure
Prefetch 限制单个 Consumer / Channel 同时拥有多少未确认 Delivery:
low prefetch → 更公平,但可能吃不满吞吐
high prefetch → 吞吐可能更高,但内存、在途量和故障重投成本增加
它是 Consumer 侧背压工具,不是越大越好,应根据处理耗时、并发度和消息大小测量。
Reject、NACK、Retry 与 DLQ
失败处理应先分类:
Transient Error → delayed retry + budget
Permanent Error → dead-letter / manual handling
Poison Message → isolate + alert + inspect
无限立即 requeue 会形成 Hot Loop,让坏消息持续占用 Consumer 和 Broker。
DLQ / DLX 的职责是隔离失败消息,便于告警、审查、修复后重放;它不是“失败消息从此不用管”的垃圾桶。
Queue 类型
Classic Queue
适合通用、非关键或单节点/低冗余需求。现代高可用主线不再是旧的 classic mirrored queue;该镜像机制已在 RabbitMQ 4.0 移除。
Quorum Queue
Quorum Queue 使用 Raft 复制 Queue 状态,面向长期存在、数据安全重要的队列。
publish to leader
→ replicate to quorum members
→ fsync / commit
→ publisher confirm
特点:
- 多数派故障容忍;
- 与 Publisher Confirm、Manual ACK 配合;
- 用额外磁盘、网络和共识延迟换数据安全;
- 不适合高频创建/删除的临时 Queue;
- 极长积压或大规模 Fanout 时应比较 Stream。
Stream
RabbitMQ Stream 更接近追加日志:支持保留、重读、Offset 和较长积压。它不是普通 Queue 的简单“高性能模式”。
顺序的真实边界
Queue 中 Delivery 有顺序,但以下情况会改变最终业务完成顺序:
- 多个 Consumer 并发;
- 每条消息处理时间不同;
- NACK / Redelivery;
- Retry Queue / DLQ;
- Consumer Crash。
如果业务严格依赖同一实体的状态演进,应增加单活 Consumer、Key-based routing、版本检查或幂等状态机,而不是只说“RabbitMQ 保序”。
典型故障推理
Publisher 超时,不知道是否已接管
使用稳定 Message ID、Publisher Confirm 和安全重试;Consumer 必须幂等。
Consumer 写库成功但 ACK 丢失
消息会 Redeliver;由唯一约束、Processed Message 表或状态机条件更新抵御重复。
Queue 持续积压
按顺序检查:
publish rate
→ consumer count / capacity
→ processing latency
→ prefetch / unacked
→ poison retry loop
→ broker disk / memory / network
→ partitioned workload or downstream dependency
适用与不适用
适合:
- 后台 Job / Work Queue;
- Command Delivery;
- 灵活 Topic / Fanout Routing;
- Retry、DLQ 和逐条 ACK;
- 中等规模业务异步解耦。
不一定适合:
- 超高吞吐、长保留、多个独立下游和频繁 Replay 的事件平台;
- 全局顺序;
- 用 Broker 替代业务数据库事务;
- 大文件传输。
观测重点
publish / deliver / ack rate
ready messages / unacked messages
redelivery and dead-letter rate
consumer count / consumer capacity
publisher confirm latency
connection / channel churn
memory / disk / file descriptors
quorum membership and leader health
面试掌握标准
- Exchange、Queue、Binding 与 Routing Key;
- Direct / Topic / Fanout 的差别;
- Publisher Confirm 与 Consumer ACK 的不同方向;
- Prefetch 如何形成背压;
- Retry、NACK、Requeue 与 DLQ 的边界;
- Quorum Queue 为什么需要 Raft 和多数派;
- Queue 顺序为什么不等于最终业务效果顺序;
- 与 Kafka、Redis Stream 的选型边界。
官方资料
- AMQP concepts: https://www.rabbitmq.com/tutorials/amqp-concepts
- Publisher confirms and consumer acknowledgements: https://www.rabbitmq.com/docs/confirms
- Quorum queues: https://www.rabbitmq.com/docs/quorum-queues
- Streams: https://www.rabbitmq.com/docs/streams