06-17-A-RabbitMQ架构与存储原理详解

06-17-A-RabbitMQ架构与存储原理详解

️ 关键词:RabbitMQ · AMQP · Exchange · Queue · Binding · Routing Key · VHost · Erlang · 经典队列 · Quorum Queue · Stream · 内存与磁盘存储

📌 导读 :三大消息队列里,RabbitMQ 是"路由最灵活 "的那个------Kafka 靠 Partition 哈希路由,RocketMQ 靠 Topic+Tag,而 RabbitMQ 靠 Exchange + Binding Key 的组合路由 ,能把一条消息按规则分发到任意多个队列。RabbitMQ 系列共四篇:本篇讲"架构与存储"(AMQP 模型、Exchange/Queue/Binding 三件套、VHost、队列的内存/磁盘存储机制、三种队列类型),10 篇讲"消息特性与消费机制"(四种 Exchange 路由、确认机制、TTL/DLX/延迟队列、消费与 prefetch),11 篇讲"高可用与生产调优"(镜像队列/Quorum Queue、集群、参数调优、积压处理),12 篇是面试与生产事故实战。看完本篇你能做到:被问"RabbitMQ 路由模型"能画出 Producer→Exchange→Binding→Queue→Consumer 图,被问"消息什么时候落盘"能讲出内存队列+惰性持久化,被问"经典队列和 Quorum Queue 怎么选"能给出对比表。


📑 目录

  • 06-17-A-RabbitMQ架构与存储原理详解
    • [📖 术语速查表(每个词都用人话解释)](#📖 术语速查表(每个词都用人话解释))
    • [一、RabbitMQ 的定位:路由最灵活的 MQ](#一、RabbitMQ 的定位:路由最灵活的 MQ)
      • [1.1 三大 MQ 分工](#1.1 三大 MQ 分工)
      • [1.2 为什么路由灵活是核心优势](#1.2 为什么路由灵活是核心优势)
    • 二、核心模型:Exchange、Queue、Binding
      • [2.1 消息流转模型](#2.1 消息流转模型)
      • [2.2 Connection 与 Channel:多路复用](#2.2 Connection 与 Channel:多路复用)
      • [2.3 与 Kafka/RocketMQ 的模型对比](#2.3 与 Kafka/RocketMQ 的模型对比)
    • 三、存储机制:消息什么时候在内存、什么时候在磁盘
      • [3.1 经典队列的存储策略](#3.1 经典队列的存储策略)
      • [3.2 三种队列类型选型](#3.2 三种队列类型选型)
      • [3.3 磁盘目录结构](#3.3 磁盘目录结构)
    • 四、集群架构:元数据与消息的分布
      • [4.1 集群的默认行为](#4.1 集群的默认行为)
      • [4.2 磁盘节点与内存节点](#4.2 磁盘节点与内存节点)
      • [4.3 客户端连接策略](#4.3 客户端连接策略)
    • 五、跑一遍:从启动到观察路由与存储
      • [5.1 启动与声明拓扑](#5.1 启动与声明拓扑)
      • [5.2 发消息观察路由](#5.2 发消息观察路由)
      • [5.3 消费与"消费即删"验证](#5.3 消费与"消费即删"验证)
    • 六、总结
      • [6.1 一张图回顾全文](#6.1 一张图回顾全文)
      • [6.2 核心要点浓缩(十二条)](#6.2 核心要点浓缩(十二条))

📖 术语速查表(每个词都用人话解释)

** AMQP 模型类**

术语 一句话白话解释
AMQP Advanced Message Queuing Protocol------RabbitMQ 实现的开放消息协议,定义了 Producer/Exchange/Queue/Consumer 的标准交互
RabbitMQ Erlang 写的 AMQP Broker------路由专家,万级 TPS,管理界面好用,中小规模业务首选
Producer 消息生产者------发消息到 Exchange(注意:不是直接发 Queue)
Exchange(交换机) 消息的"路由器"------接收 Producer 消息,按 Binding 规则分发到 Queue ------RabbitMQ 的核心抽象,自己不存消息
Queue(队列) 消息的"缓冲区"------存储消息,Consumer 从 Queue 消费------消息真正的家
Binding(绑定) Exchange 和 Queue 之间的路由规则------含 Binding Key,决定什么消息进什么 Queue
Routing Key 消息的路由键------Producer 发消息时指定,Exchange 用它匹配 Binding
Binding Key 绑定的匹配模式------Exchange 用 Routing Key 匹配 Binding Key,命中则投递到对应 Queue
VHost(虚拟主机) 逻辑隔离的"命名空间"------不同 VHost 的 Exchange/Queue 完全隔离(类似数据库的 schema)
Connection / Channel TCP 连接 / 连接内的逻辑通道------一个 Connection 多路复用多个 Channel(省 TCP 握手,线程级隔离)
默认 Exchange 名为 ""(空串)的 direct Exchange------每个 Queue 自动以队列名绑定 ,basicPublish("", "queueName") 直达队列

️ 存储类

术语 一句话白话解释
经典队列(Classic Queue) 传统队列实现------消息优先放内存,内存压力/持久化消息才写磁盘(v1/v2 两代存储引擎)
Quorum Queue 3.8+ 的基于 Raft 的高可用队列 ------多数派写入不丢数据,替代镜像队列(3.12 起官方推荐)
Stream 3.9+ 的日志型队列 ------追加写、可重复消费、百万级吞吐------Kafka 化的 RabbitMQ(日志/流场景)
持久化(durable) Exchange/Queue 元数据落盘 + 消息 deliveryMode=2------Broker 重启不丢
惰性队列(Lazy Queue) 消息直接写磁盘不进内存------百万级积压不撑爆内存(3.12+ 经典队列默认惰性行为)
Page 机制 经典队列把磁盘消息按页(32MB)组织------paging 到磁盘、内存只留索引

一、RabbitMQ 的定位:路由最灵活的 MQ

1.1 三大 MQ 分工

维度 RabbitMQ RocketMQ Kafka
协议 AMQP(开放协议) 自研 自研
语言 Erlang Java Scala/Java
路由 Exchange+Binding 组合路由(最灵活) Topic+Tag Partition 哈希
延迟消息 ✅ TTL+DLX(任意时间)/ 延迟插件 ✅ 18 等级(5.x 任意时间) ❌(生态方案)
吞吐 万级 TPS 十万级 TPS 百万级 TPS
消息回溯 ❌(消费即删) ✅(按时间/位点) ✅(按 Offset)
生态 多语言(AMQP 标准)、管理界面好 Java/阿里云生态 大数据生态
适用 中小规模、路由复杂、多语言 业务消息(事务/延迟) 日志/流处理/大数据

一句话 :RabbitMQ 是"路由专家"------Exchange+Binding 的组合路由最灵活,AMQP 开放协议多语言友好;吞吐不如 Kafka/RocketMQ,适合中小规模+复杂路由场景(完整对比见 26-A 篇)。

1.2 为什么路由灵活是核心优势

#mermaid-svg-APfB2SIkKNANhSBv{font-family:Microsoft YaHei;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-APfB2SIkKNANhSBv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-APfB2SIkKNANhSBv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-APfB2SIkKNANhSBv .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-APfB2SIkKNANhSBv .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-APfB2SIkKNANhSBv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-APfB2SIkKNANhSBv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-APfB2SIkKNANhSBv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-APfB2SIkKNANhSBv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-APfB2SIkKNANhSBv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-APfB2SIkKNANhSBv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-APfB2SIkKNANhSBv .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-APfB2SIkKNANhSBv .marker.cross{stroke:#0b0b0b;}#mermaid-svg-APfB2SIkKNANhSBv svg{font-family:Microsoft YaHei;font-size:16px;}#mermaid-svg-APfB2SIkKNANhSBv p{margin:0;}#mermaid-svg-APfB2SIkKNANhSBv .label{font-family:Microsoft YaHei;color:#333;}#mermaid-svg-APfB2SIkKNANhSBv .cluster-label text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-APfB2SIkKNANhSBv .cluster-label span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-APfB2SIkKNANhSBv .cluster-label span p{background-color:transparent;}#mermaid-svg-APfB2SIkKNANhSBv .label text,#mermaid-svg-APfB2SIkKNANhSBv span{fill:#333;color:#333;}#mermaid-svg-APfB2SIkKNANhSBv .node rect,#mermaid-svg-APfB2SIkKNANhSBv .node circle,#mermaid-svg-APfB2SIkKNANhSBv .node ellipse,#mermaid-svg-APfB2SIkKNANhSBv .node polygon,#mermaid-svg-APfB2SIkKNANhSBv .node path{fill:#fff4dd;stroke:hsl(40.5882352941, 60%, 83.3333333333%);stroke-width:1px;}#mermaid-svg-APfB2SIkKNANhSBv .rough-node .label text,#mermaid-svg-APfB2SIkKNANhSBv .node .label text,#mermaid-svg-APfB2SIkKNANhSBv .image-shape .label,#mermaid-svg-APfB2SIkKNANhSBv .icon-shape .label{text-anchor:middle;}#mermaid-svg-APfB2SIkKNANhSBv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-APfB2SIkKNANhSBv .rough-node .label,#mermaid-svg-APfB2SIkKNANhSBv .node .label,#mermaid-svg-APfB2SIkKNANhSBv .image-shape .label,#mermaid-svg-APfB2SIkKNANhSBv .icon-shape .label{text-align:center;}#mermaid-svg-APfB2SIkKNANhSBv .node.clickable{cursor:pointer;}#mermaid-svg-APfB2SIkKNANhSBv .root .anchor path{fill:#0b0b0b!important;stroke-width:0;stroke:#0b0b0b;}#mermaid-svg-APfB2SIkKNANhSBv .arrowheadPath{fill:#0b0b0b;}#mermaid-svg-APfB2SIkKNANhSBv .edgePath .path{stroke:#0b0b0b;stroke-width:2.0px;}#mermaid-svg-APfB2SIkKNANhSBv .flowchart-link{stroke:#0b0b0b;fill:none;}#mermaid-svg-APfB2SIkKNANhSBv .edgeLabel{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-APfB2SIkKNANhSBv .edgeLabel p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-APfB2SIkKNANhSBv .edgeLabel rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-APfB2SIkKNANhSBv .labelBkg{background-color:rgba(243.9999999999, 220.9999999998, 255, 0.5);}#mermaid-svg-APfB2SIkKNANhSBv .cluster rect{fill:hsl(220.5882352941, 100%, 98.3333333333%);stroke:hsl(220.5882352941, 60%, 88.3333333333%);stroke-width:1px;}#mermaid-svg-APfB2SIkKNANhSBv .cluster text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-APfB2SIkKNANhSBv .cluster span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-APfB2SIkKNANhSBv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Microsoft YaHei;font-size:12px;background:hsl(220.5882352941, 100%, 98.3333333333%);border:1px solid hsl(220.5882352941, 60%, 88.3333333333%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-APfB2SIkKNANhSBv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-APfB2SIkKNANhSBv rect.text{fill:none;stroke-width:0;}#mermaid-svg-APfB2SIkKNANhSBv .icon-shape,#mermaid-svg-APfB2SIkKNANhSBv .image-shape{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-APfB2SIkKNANhSBv .icon-shape p,#mermaid-svg-APfB2SIkKNANhSBv .image-shape p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);padding:2px;}#mermaid-svg-APfB2SIkKNANhSBv .icon-shape .label rect,#mermaid-svg-APfB2SIkKNANhSBv .image-shape .label rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-APfB2SIkKNANhSBv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-APfB2SIkKNANhSBv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-APfB2SIkKNANhSBv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 一条消息,按规则分发到多个 Queue。
fanout:广播到所有 Queue。
订单事件 → 库存 / 积分 /
通知 / 日志。

topic:按模式匹配。
order.create → 订单 Queue。
order.* → 所有订单相关 Queue。
#.error → 所有错误 Queue。

direct:精确路由。
pay.success → 支付 Queue。

Kafka / RocketMQ 做不到:
一条消息按不同规则进不同 Queue。
RabbitMQ 的 Exchange
是天然的路由层。

对比理解 :Kafka/RocketMQ 的"发布订阅"靠多个 Consumer Group 各自消费同一 Topic (消息复制给每个组);RabbitMQ 靠一条消息路由进多个 Queue (消息在 Broker 内复制)。前者订阅方决定,后者路由规则决定------RabbitMQ 的路由规则可以集中管理、动态修改,不用动生产者和消费者代码。


二、核心模型:Exchange、Queue、Binding

2.1 消息流转模型

#mermaid-svg-agmbP2EU3OarsKb6{font-family:Microsoft YaHei;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-agmbP2EU3OarsKb6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-agmbP2EU3OarsKb6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-agmbP2EU3OarsKb6 .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-agmbP2EU3OarsKb6 .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-agmbP2EU3OarsKb6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-agmbP2EU3OarsKb6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-agmbP2EU3OarsKb6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-agmbP2EU3OarsKb6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-agmbP2EU3OarsKb6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-agmbP2EU3OarsKb6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-agmbP2EU3OarsKb6 .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-agmbP2EU3OarsKb6 .marker.cross{stroke:#0b0b0b;}#mermaid-svg-agmbP2EU3OarsKb6 svg{font-family:Microsoft YaHei;font-size:16px;}#mermaid-svg-agmbP2EU3OarsKb6 p{margin:0;}#mermaid-svg-agmbP2EU3OarsKb6 .label{font-family:Microsoft YaHei;color:#333;}#mermaid-svg-agmbP2EU3OarsKb6 .cluster-label text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-agmbP2EU3OarsKb6 .cluster-label span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-agmbP2EU3OarsKb6 .cluster-label span p{background-color:transparent;}#mermaid-svg-agmbP2EU3OarsKb6 .label text,#mermaid-svg-agmbP2EU3OarsKb6 span{fill:#333;color:#333;}#mermaid-svg-agmbP2EU3OarsKb6 .node rect,#mermaid-svg-agmbP2EU3OarsKb6 .node circle,#mermaid-svg-agmbP2EU3OarsKb6 .node ellipse,#mermaid-svg-agmbP2EU3OarsKb6 .node polygon,#mermaid-svg-agmbP2EU3OarsKb6 .node path{fill:#fff4dd;stroke:hsl(40.5882352941, 60%, 83.3333333333%);stroke-width:1px;}#mermaid-svg-agmbP2EU3OarsKb6 .rough-node .label text,#mermaid-svg-agmbP2EU3OarsKb6 .node .label text,#mermaid-svg-agmbP2EU3OarsKb6 .image-shape .label,#mermaid-svg-agmbP2EU3OarsKb6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-agmbP2EU3OarsKb6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-agmbP2EU3OarsKb6 .rough-node .label,#mermaid-svg-agmbP2EU3OarsKb6 .node .label,#mermaid-svg-agmbP2EU3OarsKb6 .image-shape .label,#mermaid-svg-agmbP2EU3OarsKb6 .icon-shape .label{text-align:center;}#mermaid-svg-agmbP2EU3OarsKb6 .node.clickable{cursor:pointer;}#mermaid-svg-agmbP2EU3OarsKb6 .root .anchor path{fill:#0b0b0b!important;stroke-width:0;stroke:#0b0b0b;}#mermaid-svg-agmbP2EU3OarsKb6 .arrowheadPath{fill:#0b0b0b;}#mermaid-svg-agmbP2EU3OarsKb6 .edgePath .path{stroke:#0b0b0b;stroke-width:2.0px;}#mermaid-svg-agmbP2EU3OarsKb6 .flowchart-link{stroke:#0b0b0b;fill:none;}#mermaid-svg-agmbP2EU3OarsKb6 .edgeLabel{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-agmbP2EU3OarsKb6 .edgeLabel p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-agmbP2EU3OarsKb6 .edgeLabel rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-agmbP2EU3OarsKb6 .labelBkg{background-color:rgba(243.9999999999, 220.9999999998, 255, 0.5);}#mermaid-svg-agmbP2EU3OarsKb6 .cluster rect{fill:hsl(220.5882352941, 100%, 98.3333333333%);stroke:hsl(220.5882352941, 60%, 88.3333333333%);stroke-width:1px;}#mermaid-svg-agmbP2EU3OarsKb6 .cluster text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-agmbP2EU3OarsKb6 .cluster span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-agmbP2EU3OarsKb6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Microsoft YaHei;font-size:12px;background:hsl(220.5882352941, 100%, 98.3333333333%);border:1px solid hsl(220.5882352941, 60%, 88.3333333333%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-agmbP2EU3OarsKb6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-agmbP2EU3OarsKb6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-agmbP2EU3OarsKb6 .icon-shape,#mermaid-svg-agmbP2EU3OarsKb6 .image-shape{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-agmbP2EU3OarsKb6 .icon-shape p,#mermaid-svg-agmbP2EU3OarsKb6 .image-shape p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);padding:2px;}#mermaid-svg-agmbP2EU3OarsKb6 .icon-shape .label rect,#mermaid-svg-agmbP2EU3OarsKb6 .image-shape .label rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-agmbP2EU3OarsKb6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-agmbP2EU3OarsKb6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-agmbP2EU3OarsKb6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Binding Key = order.create
Binding Key = order.*
Binding Key = #.error
Producer。
发消息 + Routing Key。

Exchange。
路由器,按 Binding 分发。

Queue1:订单处理。
Queue2:订单统计。
Queue3:错误告警。
Consumer1。
Consumer2。
Consumer3。

关键认知:

  1. Producer 不直接发 Queue------Producer 发消息到 Exchange,由 Exchange 按 Binding 路由到 Queue;
  2. Exchange 是路由器,Queue 是缓冲区------Exchange 不存消息(只路由),Queue 存消息;
  3. 一条消息可进多个 Queue------fanout/topic 下一条消息匹配多个 Binding,复制到多个 Queue;
  4. 路由不到任何 Queue 的消息 ------默认直接丢弃 !要开启 mandatory=true(退回 Producer)或配 **备用交换机(Alternate Exchange)**兜底(10 篇详解);
  5. VHost 隔离------不同 VHost 的 Exchange/Queue 完全隔离(多租户/多环境)。

2.2 Connection 与 Channel:多路复用

text 复制代码
应用服务器 ──1 个 TCP Connection──> RabbitMQ
                ├── Channel 1(线程 A:发订单消息)
                ├── Channel 2(线程 B:发支付消息)
                └── Channel 3(线程 C:消费队列)
概念 说明
Connection TCP 长连接------建立成本高(握手+认证),一个应用 1~2 个就够
Channel Connection 内的逻辑通道------AMQP 命令都在 Channel 上走,轻量(无 TCP 开销)
军规 Channel 非线程安全------每个线程用自己的 Channel(Spring AMQP 的 RabbitTemplate 已做线程安全封装)

2.3 与 Kafka/RocketMQ 的模型对比

RabbitMQ RocketMQ Kafka
路由层 Exchange(独立路由器) Broker 内 Topic+Tag Broker 内 Partition 哈希
消息存储 Queue(消费即删) CommitLog+ConsumeQueue(按时间保留) Partition 日志(按 retention 保留)
一条消息多 Queue ✅(fanout/topic) ❌(一个 Topic 一份) ❌(一个 Partition 一份)
消费模型 推模式(Broker push 给 Consumer) 长轮询拉 拉模式(poll)
消息回溯 ❌ 消费即删 ✅ ✅
并行单位 Queue(一个 Queue 可多 Consumer 轮询) Message Queue Partition

本质差异 :RabbitMQ 是"智能 Broker + 哑 Queue "(路由逻辑在 Broker 的 Exchange),Kafka 是"哑 Broker + 智能 Consumer "(路由逻辑在 Producer 的分区器,消费进度在 Consumer)------灵活性给了 Broker,吞吐就受限;逻辑下放两端,Broker 就能做薄做快。


三、存储机制:消息什么时候在内存、什么时候在磁盘

3.1 经典队列的存储策略

#mermaid-svg-MfqRIz15fboL8IuH{font-family:Microsoft YaHei;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MfqRIz15fboL8IuH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MfqRIz15fboL8IuH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MfqRIz15fboL8IuH .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-MfqRIz15fboL8IuH .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-MfqRIz15fboL8IuH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MfqRIz15fboL8IuH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MfqRIz15fboL8IuH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MfqRIz15fboL8IuH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MfqRIz15fboL8IuH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MfqRIz15fboL8IuH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MfqRIz15fboL8IuH .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-MfqRIz15fboL8IuH .marker.cross{stroke:#0b0b0b;}#mermaid-svg-MfqRIz15fboL8IuH svg{font-family:Microsoft YaHei;font-size:16px;}#mermaid-svg-MfqRIz15fboL8IuH p{margin:0;}#mermaid-svg-MfqRIz15fboL8IuH .label{font-family:Microsoft YaHei;color:#333;}#mermaid-svg-MfqRIz15fboL8IuH .cluster-label text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-MfqRIz15fboL8IuH .cluster-label span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-MfqRIz15fboL8IuH .cluster-label span p{background-color:transparent;}#mermaid-svg-MfqRIz15fboL8IuH .label text,#mermaid-svg-MfqRIz15fboL8IuH span{fill:#333;color:#333;}#mermaid-svg-MfqRIz15fboL8IuH .node rect,#mermaid-svg-MfqRIz15fboL8IuH .node circle,#mermaid-svg-MfqRIz15fboL8IuH .node ellipse,#mermaid-svg-MfqRIz15fboL8IuH .node polygon,#mermaid-svg-MfqRIz15fboL8IuH .node path{fill:#fff4dd;stroke:hsl(40.5882352941, 60%, 83.3333333333%);stroke-width:1px;}#mermaid-svg-MfqRIz15fboL8IuH .rough-node .label text,#mermaid-svg-MfqRIz15fboL8IuH .node .label text,#mermaid-svg-MfqRIz15fboL8IuH .image-shape .label,#mermaid-svg-MfqRIz15fboL8IuH .icon-shape .label{text-anchor:middle;}#mermaid-svg-MfqRIz15fboL8IuH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MfqRIz15fboL8IuH .rough-node .label,#mermaid-svg-MfqRIz15fboL8IuH .node .label,#mermaid-svg-MfqRIz15fboL8IuH .image-shape .label,#mermaid-svg-MfqRIz15fboL8IuH .icon-shape .label{text-align:center;}#mermaid-svg-MfqRIz15fboL8IuH .node.clickable{cursor:pointer;}#mermaid-svg-MfqRIz15fboL8IuH .root .anchor path{fill:#0b0b0b!important;stroke-width:0;stroke:#0b0b0b;}#mermaid-svg-MfqRIz15fboL8IuH .arrowheadPath{fill:#0b0b0b;}#mermaid-svg-MfqRIz15fboL8IuH .edgePath .path{stroke:#0b0b0b;stroke-width:2.0px;}#mermaid-svg-MfqRIz15fboL8IuH .flowchart-link{stroke:#0b0b0b;fill:none;}#mermaid-svg-MfqRIz15fboL8IuH .edgeLabel{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-MfqRIz15fboL8IuH .edgeLabel p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-MfqRIz15fboL8IuH .edgeLabel rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-MfqRIz15fboL8IuH .labelBkg{background-color:rgba(243.9999999999, 220.9999999998, 255, 0.5);}#mermaid-svg-MfqRIz15fboL8IuH .cluster rect{fill:hsl(220.5882352941, 100%, 98.3333333333%);stroke:hsl(220.5882352941, 60%, 88.3333333333%);stroke-width:1px;}#mermaid-svg-MfqRIz15fboL8IuH .cluster text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-MfqRIz15fboL8IuH .cluster span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-MfqRIz15fboL8IuH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Microsoft YaHei;font-size:12px;background:hsl(220.5882352941, 100%, 98.3333333333%);border:1px solid hsl(220.5882352941, 60%, 88.3333333333%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MfqRIz15fboL8IuH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MfqRIz15fboL8IuH rect.text{fill:none;stroke-width:0;}#mermaid-svg-MfqRIz15fboL8IuH .icon-shape,#mermaid-svg-MfqRIz15fboL8IuH .image-shape{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-MfqRIz15fboL8IuH .icon-shape p,#mermaid-svg-MfqRIz15fboL8IuH .image-shape p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);padding:2px;}#mermaid-svg-MfqRIz15fboL8IuH .icon-shape .label rect,#mermaid-svg-MfqRIz15fboL8IuH .image-shape .label rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-MfqRIz15fboL8IuH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MfqRIz15fboL8IuH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MfqRIz15fboL8IuH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
消息到达 Queue。
消息持久化?

deliveryMode = 2
是 →
写入持久化存储。
消息索引 + 内容落盘。
同时保留内存副本加速投递。

否 → 只放内存。
Broker 重启即丢。

内存压力 / 积压增长?
是 → Paging。
消息按页(32MB)换出到磁盘。
内存只留索引。

否 → 内存投递,
最快路径。

Consumer 消费时
按页读回。

三个关键结论:

  1. "持久化消息"≠"每条都实时刷盘" ------持久化消息先写盘再进内存副本,但批量/异步落盘 ;Broker 断电仍可能丢最后几毫秒的消息(要绝对不丢必须 Publisher Confirm 等到落盘确认,10 篇);
  2. 积压时 Paging 会拖慢性能 ------消息换出磁盘再读回,吞吐骤降;惰性队列(Lazy Queue)直接写磁盘不进内存,百万积压也稳定(3.12+ 经典队列默认此行为);
  3. 内存水位保护 ------RabbitMQ 内存超阈值(默认物理内存 40%)会阻塞所有 Producer(flow control),防止 OOM 崩溃(11 篇调优)。

3.2 三种队列类型选型

维度 经典队列(Classic) Quorum Queue Stream
存储 内存优先+磁盘 paging WAL+Raft 复制,磁盘为主 追加日志(类 Kafka)
高可用 靠镜像(已废弃) Raft 多数派(内置) 复制日志
消费模型 消费即删 消费即删 可重复消费(按 Offset)
吞吐 万级 万级(多数派写入略低) 十万级+
功能支持 全(TTL/DLX/优先级) 大部分(DLX✅ 优先级❌) 少(无 DLX/TTL)
适用 常规业务(存量) 高可靠业务(新集群首选) 日志/事件溯源/流处理

一句话 :新集群业务队列直接上 Quorum Queue(Raft 不丢+免配镜像),日志流场景试 Stream,经典队列是存量兼容------镜像队列已废弃不要再上。

3.3 磁盘目录结构

text 复制代码
/var/lib/rabbitmq/mnesia/rabbit@node1/
├── queues/
│   └── <vhost-hash>/
│       └── <queue-uuid>/
│           ├── 00000001.wal      ← Quorum Queue 的 WAL(Raft 日志)
│           └── msg_store_durable/ ← 经典队列持久化消息存储
├── msg_stores/
│   └── vhosts/<vhost-hash>/msg_store_persistent/
│       ├── 0000000000000001.rdq  ← 消息内容文件(按 16MB 分段)
│       └── msg_store_index.ets   ← 消息索引(ETS 内存表)
└── rabbit_durable_exchange.ets   ← Exchange/Binding 元数据(durable 的)

消息存储是 VHost 级共享的 (msg_store)------同一 VHost 所有队列的持久化消息存在一起(类似 RocketMQ 混写 CommitLog 的思想),队列里只存索引;小消息(<4KB 默认)直接内嵌索引里(embedding),省一次寻址。


四、集群架构:元数据与消息的分布

4.1 集群的默认行为

#mermaid-svg-e3GUFCFSSpNI2ifa{font-family:Microsoft YaHei;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-e3GUFCFSSpNI2ifa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-e3GUFCFSSpNI2ifa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-e3GUFCFSSpNI2ifa .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-e3GUFCFSSpNI2ifa .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-e3GUFCFSSpNI2ifa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-e3GUFCFSSpNI2ifa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-e3GUFCFSSpNI2ifa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-e3GUFCFSSpNI2ifa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-e3GUFCFSSpNI2ifa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-e3GUFCFSSpNI2ifa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-e3GUFCFSSpNI2ifa .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-e3GUFCFSSpNI2ifa .marker.cross{stroke:#0b0b0b;}#mermaid-svg-e3GUFCFSSpNI2ifa svg{font-family:Microsoft YaHei;font-size:16px;}#mermaid-svg-e3GUFCFSSpNI2ifa p{margin:0;}#mermaid-svg-e3GUFCFSSpNI2ifa .label{font-family:Microsoft YaHei;color:#333;}#mermaid-svg-e3GUFCFSSpNI2ifa .cluster-label text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-e3GUFCFSSpNI2ifa .cluster-label span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-e3GUFCFSSpNI2ifa .cluster-label span p{background-color:transparent;}#mermaid-svg-e3GUFCFSSpNI2ifa .label text,#mermaid-svg-e3GUFCFSSpNI2ifa span{fill:#333;color:#333;}#mermaid-svg-e3GUFCFSSpNI2ifa .node rect,#mermaid-svg-e3GUFCFSSpNI2ifa .node circle,#mermaid-svg-e3GUFCFSSpNI2ifa .node ellipse,#mermaid-svg-e3GUFCFSSpNI2ifa .node polygon,#mermaid-svg-e3GUFCFSSpNI2ifa .node path{fill:#fff4dd;stroke:hsl(40.5882352941, 60%, 83.3333333333%);stroke-width:1px;}#mermaid-svg-e3GUFCFSSpNI2ifa .rough-node .label text,#mermaid-svg-e3GUFCFSSpNI2ifa .node .label text,#mermaid-svg-e3GUFCFSSpNI2ifa .image-shape .label,#mermaid-svg-e3GUFCFSSpNI2ifa .icon-shape .label{text-anchor:middle;}#mermaid-svg-e3GUFCFSSpNI2ifa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-e3GUFCFSSpNI2ifa .rough-node .label,#mermaid-svg-e3GUFCFSSpNI2ifa .node .label,#mermaid-svg-e3GUFCFSSpNI2ifa .image-shape .label,#mermaid-svg-e3GUFCFSSpNI2ifa .icon-shape .label{text-align:center;}#mermaid-svg-e3GUFCFSSpNI2ifa .node.clickable{cursor:pointer;}#mermaid-svg-e3GUFCFSSpNI2ifa .root .anchor path{fill:#0b0b0b!important;stroke-width:0;stroke:#0b0b0b;}#mermaid-svg-e3GUFCFSSpNI2ifa .arrowheadPath{fill:#0b0b0b;}#mermaid-svg-e3GUFCFSSpNI2ifa .edgePath .path{stroke:#0b0b0b;stroke-width:2.0px;}#mermaid-svg-e3GUFCFSSpNI2ifa .flowchart-link{stroke:#0b0b0b;fill:none;}#mermaid-svg-e3GUFCFSSpNI2ifa .edgeLabel{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-e3GUFCFSSpNI2ifa .edgeLabel p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-e3GUFCFSSpNI2ifa .edgeLabel rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-e3GUFCFSSpNI2ifa .labelBkg{background-color:rgba(243.9999999999, 220.9999999998, 255, 0.5);}#mermaid-svg-e3GUFCFSSpNI2ifa .cluster rect{fill:hsl(220.5882352941, 100%, 98.3333333333%);stroke:hsl(220.5882352941, 60%, 88.3333333333%);stroke-width:1px;}#mermaid-svg-e3GUFCFSSpNI2ifa .cluster text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-e3GUFCFSSpNI2ifa .cluster span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-e3GUFCFSSpNI2ifa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Microsoft YaHei;font-size:12px;background:hsl(220.5882352941, 100%, 98.3333333333%);border:1px solid hsl(220.5882352941, 60%, 88.3333333333%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-e3GUFCFSSpNI2ifa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-e3GUFCFSSpNI2ifa rect.text{fill:none;stroke-width:0;}#mermaid-svg-e3GUFCFSSpNI2ifa .icon-shape,#mermaid-svg-e3GUFCFSSpNI2ifa .image-shape{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-e3GUFCFSSpNI2ifa .icon-shape p,#mermaid-svg-e3GUFCFSSpNI2ifa .image-shape p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);padding:2px;}#mermaid-svg-e3GUFCFSSpNI2ifa .icon-shape .label rect,#mermaid-svg-e3GUFCFSSpNI2ifa .image-shape .label rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-e3GUFCFSSpNI2ifa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-e3GUFCFSSpNI2ifa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-e3GUFCFSSpNI2ifa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} RabbitMQ 集群(3 节点)。
元数据全节点同步
Exchange/Queue/Binding/VHost 定义
用户/权限------所有节点都有全量。

消息内容默认不复制!
Queue 的消息只在'宿主节点'
其他节点收到该 Queue 的请求
→ 转发到宿主节点。

后果:宿主节点挂
Queue 不可用(未持久化消息丢)
→ 要高可用必须 Quorum/镜像。

关键认知 :RabbitMQ 集群 ≠ 高可用------集群解决的是"元数据共享+连接分散",消息复制要靠 Quorum Queue(或旧镜像队列,11 篇详解)。

4.2 磁盘节点与内存节点

节点类型 元数据存储 说明
磁盘节点(disc,默认) 内存 + 磁盘 集群至少 1 个磁盘节点(元数据持久化)
内存节点(ram) 仅内存 性能略好,重启元数据靠其他节点恢复------现在意义不大,全用磁盘节点

4.3 客户端连接策略

text 复制代码
① 直连多节点:客户端配置多个地址(host1:5672,host2:5672,host3:5672)
   ------连接失败自动试下一个(Spring AMQP 原生支持地址列表)
② 负载均衡:HAProxy/LVS 前置,客户端只连 VIP
   ------生产大集群推荐(连接管理集中,节点变更不动客户端)
③ 注意:连到非宿主节点的 Queue 请求会被"透明转发"------
   跨节点转发有额外开销,Queue 宿主与 Consumer 所在节点一致最优

五、跑一遍:从启动到观察路由与存储

下面是可以直接照做的实操示例(Docker 单机 + rabbitmqadmin 管理命令行),每一步给出真实结果。

5.1 启动与声明拓扑

shell 复制代码
# ① Docker 启动(带管理界面)
docker run -d --name rabbit -p 5672:5672 -p 15672:15672 \
  rabbitmq:3.13-management
# 管理界面:http://localhost:15672(guest/guest)

# ② 声明拓扑:topic Exchange + 两个 Queue + 绑定
docker exec rabbit rabbitmqadmin declare exchange name=order-exchange type=topic durable=true
docker exec rabbit rabbitmqadmin declare queue name=order-create-queue durable=true
docker exec rabbit rabbitmqadmin declare queue name=order-all-queue durable=true
docker exec rabbit rabbitmqadmin declare binding source=order-exchange \
  destination=order-create-queue routing_key="order.create"
docker exec rabbit rabbitmqadmin declare binding source=order-exchange \
  destination=order-all-queue routing_key="order.*"

# ③ 查看绑定关系
docker exec rabbit rabbitmqadmin list bindings source_name destination_name routing_key

③ 的输出(两条 Binding 规则就位):

text 复制代码
+----------------+----------------------+--------------+
| source_name    | destination_name     | routing_key  |
+----------------+----------------------+--------------+
| order-exchange | order-create-queue   | order.create |
| order-exchange | order-all-queue      | order.*      |
+----------------+----------------------+--------------+

5.2 发消息观察路由

shell 复制代码
# ④ 发一条 Routing Key = order.create 的消息(持久化)
docker exec rabbit rabbitmqadmin publish exchange=order-exchange \
  routing_key=order.create payload='{"orderId":1001,"action":"create"}' \
  properties='{"delivery_mode":2}'
# 输出:Message published

# ⑤ 查看两个队列的消息数
docker exec rabbit rabbitmqadmin list queues name messages messages_ready

⑤ 的输出 (一条消息同时进了两个 Queue------topic 通配符路由的直观体现):

text 复制代码
+--------------------+----------+----------------+
| name               | messages | messages_ready |
+--------------------+----------+----------------+
| order-all-queue    | 1        | 1              |
| order-create-queue | 1        | 1              |
+--------------------+----------+----------------+

5.3 消费与"消费即删"验证

shell 复制代码
# ⑥ 从 order-create-queue 取一条消息(ack 后删除)
docker exec rabbit rabbitmqadmin get queue=order-create-queue ackmode=ack_requeue_false count=1

⑥ 的输出:

text 复制代码
+--------------------+--------------+---------------+-----------------------------+
| routing_key        | exchange     | message_count | payload                     |
+--------------------+--------------+---------------+-----------------------------+
| order.create       | order-exchange| 1           | {"orderId":1001,"action":"create"} |
+--------------------+--------------+---------------+-----------------------------+

# ⑦ 再查队列:order-create-queue 已空,order-all-queue 还有 1 条
docker exec rabbit rabbitmqadmin list queues name messages
# | order-all-queue    | 1  |
# | order-create-queue | 0  |   ← 消费即删!没有"回溯重放"

💡 对照理解 :⑤证明"一条消息进多个 Queue "(Kafka/RocketMQ 做不到,它们靠多 Consumer Group);⑦证明"消费即删 "------Queue 是真正的"队列"不是"日志",消息被 ack 后就删除,没有 Kafka 式的按 Offset 回溯重放能力(要重放只能靠 Producer 重发或死信重投)。这两个行为都源自 2.3 节的模型差异:RabbitMQ 把智能放在 Broker(路由+队列管理),代价是存储模型简单、吞吐受限。


六、总结

6.1 一张图回顾全文

#mermaid-svg-F39L0lEmR89w4DJK{font-family:Microsoft YaHei;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-F39L0lEmR89w4DJK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-F39L0lEmR89w4DJK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-F39L0lEmR89w4DJK .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-F39L0lEmR89w4DJK .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-F39L0lEmR89w4DJK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-F39L0lEmR89w4DJK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-F39L0lEmR89w4DJK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-F39L0lEmR89w4DJK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-F39L0lEmR89w4DJK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-F39L0lEmR89w4DJK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-F39L0lEmR89w4DJK .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-F39L0lEmR89w4DJK .marker.cross{stroke:#0b0b0b;}#mermaid-svg-F39L0lEmR89w4DJK svg{font-family:Microsoft YaHei;font-size:16px;}#mermaid-svg-F39L0lEmR89w4DJK p{margin:0;}#mermaid-svg-F39L0lEmR89w4DJK .label{font-family:Microsoft YaHei;color:#333;}#mermaid-svg-F39L0lEmR89w4DJK .cluster-label text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-F39L0lEmR89w4DJK .cluster-label span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-F39L0lEmR89w4DJK .cluster-label span p{background-color:transparent;}#mermaid-svg-F39L0lEmR89w4DJK .label text,#mermaid-svg-F39L0lEmR89w4DJK span{fill:#333;color:#333;}#mermaid-svg-F39L0lEmR89w4DJK .node rect,#mermaid-svg-F39L0lEmR89w4DJK .node circle,#mermaid-svg-F39L0lEmR89w4DJK .node ellipse,#mermaid-svg-F39L0lEmR89w4DJK .node polygon,#mermaid-svg-F39L0lEmR89w4DJK .node path{fill:#fff4dd;stroke:hsl(40.5882352941, 60%, 83.3333333333%);stroke-width:1px;}#mermaid-svg-F39L0lEmR89w4DJK .rough-node .label text,#mermaid-svg-F39L0lEmR89w4DJK .node .label text,#mermaid-svg-F39L0lEmR89w4DJK .image-shape .label,#mermaid-svg-F39L0lEmR89w4DJK .icon-shape .label{text-anchor:middle;}#mermaid-svg-F39L0lEmR89w4DJK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-F39L0lEmR89w4DJK .rough-node .label,#mermaid-svg-F39L0lEmR89w4DJK .node .label,#mermaid-svg-F39L0lEmR89w4DJK .image-shape .label,#mermaid-svg-F39L0lEmR89w4DJK .icon-shape .label{text-align:center;}#mermaid-svg-F39L0lEmR89w4DJK .node.clickable{cursor:pointer;}#mermaid-svg-F39L0lEmR89w4DJK .root .anchor path{fill:#0b0b0b!important;stroke-width:0;stroke:#0b0b0b;}#mermaid-svg-F39L0lEmR89w4DJK .arrowheadPath{fill:#0b0b0b;}#mermaid-svg-F39L0lEmR89w4DJK .edgePath .path{stroke:#0b0b0b;stroke-width:2.0px;}#mermaid-svg-F39L0lEmR89w4DJK .flowchart-link{stroke:#0b0b0b;fill:none;}#mermaid-svg-F39L0lEmR89w4DJK .edgeLabel{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-F39L0lEmR89w4DJK .edgeLabel p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-F39L0lEmR89w4DJK .edgeLabel rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-F39L0lEmR89w4DJK .labelBkg{background-color:rgba(243.9999999999, 220.9999999998, 255, 0.5);}#mermaid-svg-F39L0lEmR89w4DJK .cluster rect{fill:hsl(220.5882352941, 100%, 98.3333333333%);stroke:hsl(220.5882352941, 60%, 88.3333333333%);stroke-width:1px;}#mermaid-svg-F39L0lEmR89w4DJK .cluster text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-F39L0lEmR89w4DJK .cluster span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-F39L0lEmR89w4DJK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Microsoft YaHei;font-size:12px;background:hsl(220.5882352941, 100%, 98.3333333333%);border:1px solid hsl(220.5882352941, 60%, 88.3333333333%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-F39L0lEmR89w4DJK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-F39L0lEmR89w4DJK rect.text{fill:none;stroke-width:0;}#mermaid-svg-F39L0lEmR89w4DJK .icon-shape,#mermaid-svg-F39L0lEmR89w4DJK .image-shape{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-F39L0lEmR89w4DJK .icon-shape p,#mermaid-svg-F39L0lEmR89w4DJK .image-shape p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);padding:2px;}#mermaid-svg-F39L0lEmR89w4DJK .icon-shape .label rect,#mermaid-svg-F39L0lEmR89w4DJK .image-shape .label rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-F39L0lEmR89w4DJK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-F39L0lEmR89w4DJK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-F39L0lEmR89w4DJK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} RabbitMQ 架构与存储。
路由模型。
Producer → Exchange → Binding
→ Queue → Consumer。
Exchange 只路由不存储。
一条消息可进多个 Queue。
路由不到默认丢弃
(mandatory / AE 兜底)。
VHost 隔离,Channel 多路复用。

存储机制。
经典队列:内存优先 + paging 换出。
持久化 ≠ 实时刷盘
(confirm 才保不丢)。
惰性队列:直接写磁盘抗积压。
msg_store VHost 级共享
(类 CommitLog)。

队列类型。
Classic:存量兼容。
Quorum:Raft 多数派,新集群首选。
Stream:日志型可回溯,流场景。

集群。
元数据全节点同步。
消息默认不复制!
集群 ≠ 高可用。
Quorum / 镜像才有消息冗余。

6.2 核心要点浓缩(十二条)

  1. RabbitMQ 定位 :路由最灵活的 MQ------Exchange+Binding 组合路由,AMQP 开放协议多语言友好;吞吐万级,适合中小规模+复杂路由。
  2. 核心模型 :Producer→Exchange→Binding→Queue→Consumer------Producer 不直接发 Queue,Exchange 是路由器(不存消息),Queue 是缓冲区(存消息)。
  3. 一条消息多 Queue :fanout/topic 下一条消息匹配多个 Binding 复制到多个 Queue------Kafka/RocketMQ 靠多 Consumer Group 实现类似效果。
  4. 路由不到默认丢弃 :要 mandatory=true 退回 Producer 或配备用交换机(AE)兜底------上线前必测"路由不到的消息去哪了"。
  5. Connection/Channel :一个 TCP Connection 多路复用多个 Channel------Channel 非线程安全,每线程一个。
  6. 智能 Broker vs 哑 Broker :RabbitMQ 路由逻辑在 Broker(灵活但吞吐受限),Kafka 逻辑下放两端(薄 Broker 高吞吐)------模型差异决定所有行为差异。
  7. 经典队列存储 :内存优先,持久化消息落盘+内存副本,积压时 paging 换出------"持久化"≠"实时刷盘",断电仍可能丢最后几毫秒(要 Publisher Confirm)。
  8. 惰性队列 :消息直接写磁盘不进内存------百万级积压不撑爆内存(3.12+ 经典队列默认惰性)。
  9. msg_store 共享存储 :VHost 级消息集中存储、队列只存索引(小消息内嵌)------和 RocketMQ 混写 CommitLog 同款思想。
  10. 三种队列类型 :Classic(存量)、Quorum(Raft 多数派,新集群首选) 、Stream(日志型可回溯)------镜像队列已废弃。
  11. 集群 ≠ 高可用 :元数据全节点同步,消息内容默认只在宿主节点------要高可用必须 Quorum/镜像队列。
  12. 连接策略 :客户端配多地址自动切换,或 HAProxy 前置------Queue 宿主与 Consumer 同节点最优(跨节点转发有开销)。

📌 最后一句话 :RabbitMQ 的设计哲学是"路由与存储分离 "------Exchange 只管路由(不存消息),Queue 只管存储(不管路由),Binding 是两者的契约。这种分离让路由规则可以任意组合(一条消息进多个 Queue、按模式匹配、按属性分发),灵活性的代价是吞吐不如 Kafka/RocketMQ。理解了"智能 Broker"的模型,下一篇的确认机制、TTL/DLX/延迟队列就都是"在这个模型上长出来的特性"。


📌 配套阅读:

上一篇:《06-16-B-Kafka面试与生产事故实战.md》

下一篇:《06-18-A-RabbitMQ消息特性与消费机制详解.md》

如果这篇文章对你有帮助,欢迎点赞、收藏、关注!

相关推荐
做个文艺程序员11 小时前
MQ第03篇:RabbitMQ进阶实战:Topic路由+死信队列+延迟消息,SaaS订单超时取消完整方案
分布式·消息队列·rabbitmq·死信队列·延迟队列
此时不提桶,更待何时1 天前
06-18-A-RabbitMQ消息特性与消费机制详解
分布式·rabbitmq
此时不提桶,更待何时1 天前
06-19-A-RabbitMQ高可用与生产调优详解
rabbitmq
做个文艺程序员2 天前
MQ第02篇:RabbitMQ快速上手教程:AMQP模型详解+Spring Boot整合实战(附完整代码)
spring boot·消息队列·rabbitmq·java-rabbitmq·amqp
yexianglunbai3 天前
RabbitMQ 详解:从入门到实战
分布式·rabbitmq
程序猿乐锅4 天前
从0-1一文详解RabbitMQ
java·分布式·后端·中间件·rabbitmq·ruby
新鲜势力呀4 天前
PHP 消息队列实战:从同步接口阻塞到 RabbitMQ + Redis队列 + 异步任务架构完整优化方案
redis·rabbitmq·php
xxwl5855 天前
RabbitMQ 学习笔记
笔记·学习·rabbitmq