← [ BACK_TO_NOTES ]

RabbitMQ

RabbitMQ 的后端工程主笔记:从 Exchange/Queue/Binding、ACK/Confirm、Prefetch、DLQ/Retry,到 Quorum Queue、路由模型、高可用和与 Kafka 的选型边界。

#concept #growing #backend #architecture

[!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 类型

类型路由方式典型场景
DirectRouting 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 的选型边界。

官方资料

创建于 2026/9/4 更新于 2026/9/4
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本