【RabbitMQ】架构与集群模式详解

RabbitMQ架构与集群模式详解

前言

假设你维护了两个服务 A 和 B。A 服务负责转发用户请求到 B 服务,B 服务是个算法服务,GPU 资源有限。当请求量大到 B 服务处理不过来的时候,希望能优先处理会员用户的请求。怎么实现?答案是 RabbitMQ 的优先级队列。本文将带你深入了解 RabbitMQ 的核心概念和集群架构。

🏠个人主页:你的主页


文章目录


一、RabbitMQ核心概念

1.1 Queue(队列)

消息队列本质上就是一个类似链表的独立进程,链表里的每个节点是一条消息。

复制代码
生产者 → [消息1] → [消息2] → [消息3] → 消费者
              ↑ 这就是 Queue

Queue 的作用是什么?削峰填谷

在流量高峰时先暂存数据,再慢慢消费,保护下游服务不被打垮。

打个比方:Queue 就像银行的叫号系统,客户来了先取号排队,柜员按顺序处理,不会因为人多就手忙脚乱。

但消息也分很多种类,比如订单消息和用户消息是两类。为了更好地管理不同种类的数据,RabbitMQ 支持创建多个队列

复制代码
RabbitMQ
├── order-queue      →  订单消息
├── user-queue       →  用户消息
└── payment-queue    →  支付消息

每个 Queue 都是独立的进程,某个进程挂了,不影响其他进程正常工作。

1.2 Exchange(交换器)

有了多个队列,新的问题来了:

  • 有些生产者想把消息发到一个 Queue
  • 有些想发到多个 Queue
  • 有些想广播给所有 Queue

怎么实现这种灵活的路由?答案是 Exchange(交换器)

Exchange 是消息的路由中心,生产者不直接发消息给 Queue,而是发给 Exchange,由 Exchange 根据规则分发到对应的 Queue。

复制代码
生产者 → Exchange → Queue-1
              ↘ → Queue-2
              ↘ → Queue-3

Exchange 和 Queue 之间通过 Binding Key(绑定键) 建立绑定关系,类似正则表达式,声明"什么样的消息发到哪个队列"。

四种 Exchange 类型

类型 路由规则 场景
Direct 精确匹配 Routing Key 点对点,一对一
Fanout 广播给所有绑定的队列 广播通知
Topic 通配符匹配(*# 灵活路由
Headers 根据消息头匹配 复杂路由(少用)

举个例子

复制代码
# Topic Exchange 示例
Routing Key: order.created  →  匹配 order.*  →  发到订单队列
Routing Key: order.paid     →  匹配 order.*  →  发到订单队列
Routing Key: user.login     →  匹配 user.*   →  发到用户队列

1.3 Broker

一台服务器上的 RabbitMQ 实例,就是一个 Broker

复制代码
Broker(RabbitMQ 实例)
├── Exchange-1
├── Exchange-2
├── Queue-1
├── Queue-2
└── Queue-3

Broker 里维护的路由规则和绑定关系,统称为元数据(Metadata)

1.4 整体架构图

复制代码
┌─────────────────────────────────────────────────────────┐
│                      Broker                             │
│  ┌──────────┐                                           │
│  │ Exchange │──bindingKey──→ Queue-1 ──→ Consumer-1    │
│  │          │──bindingKey──→ Queue-2 ──→ Consumer-2    │
│  └──────────┘──bindingKey──→ Queue-3 ──→ Consumer-3    │
│       ↑                                                 │
└───────│─────────────────────────────────────────────────┘
        │
    Producer

二、RabbitMQ的特色功能

RabbitMQ 功能非常丰富,你能想到的 MQ 功能它基本都实现了。

2.1 延迟队列

场景:用户下单后 30 分钟未支付,自动取消订单。

RabbitMQ 通过死信队列 + TTL 或者延迟插件实现延迟消息。

复制代码
订单创建 → 延迟队列(30分钟后投递) → 检查支付状态 → 未支付则取消

2.2 死信队列

消息在以下情况会变成"死信":

  • 消息被拒绝(reject/nack)且不重新入队
  • 消息过期(TTL 到期)
  • 队列达到最大长度

死信会被转发到专门的死信队列(DLX),方便后续排查和处理。

2.3 优先级队列(重点)

这是 RabbitMQ 的特色功能,也是开头问题的解决方案。

原理 :生产者发送消息时,可以为消息标记优先级(0-255),消费者总是优先消费优先级高的消息。

java 复制代码
// 声明优先级队列(最大优先级为 10)
Map<String, Object> args = new HashMap<>();
args.put("x-max-priority", 10);
channel.queueDeclare("priority-queue", true, false, false, args);

// 发送高优先级消息(会员用户)
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
    .priority(9)  // 高优先级
    .build();
channel.basicPublish("", "priority-queue", props, "VIP用户请求".getBytes());

// 发送低优先级消息(普通用户)
AMQP.BasicProperties props2 = new AMQP.BasicProperties.Builder()
    .priority(1)  // 低优先级
    .build();
channel.basicPublish("", "priority-queue", props2, "普通用户请求".getBytes());

回到开头的场景

复制代码
用户请求 → A服务(根据会员等级设置优先级) → RabbitMQ → B服务(GPU算法服务)
                                                          ↓
                                              优先消费高优消息
  • 会员用户的请求:优先级设为 9
  • 普通用户的请求:优先级设为 1
  • B 服务永远优先处理会员请求,处理完后再处理普通请求

实际应用:现在到处都是 AI,恨不得把一块 GPU 掰成 10 块用。比如某聊天 AI,当服务遭到大量访问时,免费用户会感觉很慢甚至报错,但会员用户依旧响应丝滑。背后很可能就是优先级队列在起作用。


三、单节点的问题

虽然 RabbitMQ 功能很丰富,但它的基础架构就是个单实例节点,存在明显问题:

问题 说明
单点故障 Broker 挂了,整个服务不可用
性能瓶颈 单节点处理能力有限
无法扩展 流量增长时没法水平扩容

怎么解决?上集群。


四、普通集群模式

4.1 架构设计

多个服务器各部署一个 RabbitMQ 实例,通过 RabbitMQ 提供的命令组成集群。

复制代码
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  Broker-1   │    │  Broker-2   │    │  Broker-3   │
│  ┌───────┐  │    │  ┌───────┐  │    │  ┌───────┐  │
│  │ Q1    │  │    │  │ Q2    │  │    │  │ Q3    │  │
│  └───────┘  │    │  └───────┘  │    │  └───────┘  │
│  Exchange   │←──→│  Exchange   │←──→│  Exchange   │
│  (元数据同步) │    │  (元数据同步) │    │  (元数据同步) │
└─────────────┘    └─────────────┘    └─────────────┘

关键特点

  • 每个 Broker 都是完整功能的 RabbitMQ 实例,都能进行读写
  • Broker 之间会互相同步 Exchange 里的元数据
  • 不会同步 Queue 里的数据

4.2 读写流程

写操作

复制代码
生产者 → Broker-1 → Q1(数据只存在 Broker-1)
                    ↓
         元数据同步到 Broker-2、Broker-3

Q1 里的消息数据不会同步给其他 Broker,但 Exchange 的元数据会同步。

读操作

情况一:消费者访问 Q1 所在的 Broker-1

复制代码
消费者 → Broker-1 → Q1 → 直接返回数据 ✅

情况二:消费者访问 Broker-2(但 Q1 在 Broker-1)

复制代码
消费者 → Broker-2 → 查元数据发现 Q1 在 Broker-1
                    ↓
         从 Broker-1 读取数据 → 返回给消费者

4.3 优缺点

优点 缺点
提升整体吞吐量 单个 Queue 的读写能力没提升
支持水平扩展 每个 Broker 仍有单点问题
部署简单 Queue 所在 Broker 挂了,该 Queue 就不可用

结论 :普通集群模式提升了扩展性,但没有解决高可用问题


五、镜像队列集群模式

5.1 设计思路

既然单个 Queue 有单点问题,那就给它加几个副本

打个比方:就像你手机里存了很多重要照片,为了防止手机丢了照片没了,你会把照片备份到云盘。镜像队列就是给 Queue 做备份。

5.2 架构设计

复制代码
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  Broker-1   │    │  Broker-2   │    │  Broker-3   │
│  ┌───────┐  │    │  ┌───────┐  │    │  ┌───────┐  │
│  │Q1(主) │──────→│ Q1(镜像)│──────→│ Q1(镜像)│  │
│  └───────┘  │    │  └───────┘  │    │  └───────┘  │
│             │    │  ┌───────┐  │    │             │
│             │    │  │Q2(主) │  │    │             │
│             │    │  └───────┘  │    │             │
└─────────────┘    └─────────────┘    └─────────────┘
  • 主队列(Master):负责读写数据
  • 镜像队列(Mirror):负责同步复制主队列数据
  • 主队列所在的 Broker 挂了,镜像队列可以顶上成为新的主队列

5.3 读写流程

写操作

复制代码
生产者 → Broker-1 → Q1(主)
                    ↓ 同步
         Q1(镜像)@Broker-2、Q1(镜像)@Broker-3

数据写入主队列后,会同步到所有镜像队列。

读操作

情况一:消费者访问主队列所在的 Broker

复制代码
消费者 → Broker-1 → Q1(主) → 直接返回数据 ✅

情况二:消费者访问其他 Broker

复制代码
消费者 → Broker-2 → 从 Broker-1 的 Q1(主) 读取 → 返回数据

注意:即使 Broker-2 上有 Q1 的镜像,读操作也是从主队列读取,镜像只用于故障转移。

5.4 故障转移

复制代码
Broker-1 挂了!
    ↓
Q1(镜像)@Broker-2 自动升级为 Q1(主)
    ↓
服务继续可用 ✅

5.5 优缺点

优点 缺点
实现高可用 牺牲吞吐量(数据要同步多份)
自动故障转移 网络带宽消耗大
数据不丢失 同步延迟可能导致数据不一致

结论 :镜像队列模式通过牺牲吞吐量换取高可用


六、Quorum队列模式

6.1 镜像队列的问题

RabbitMQ 基于 Erlang 语言开发。Erlang 是个很特别的语言,自带虚拟机和分布式通信框架。RabbitMQ 通过这个框架在 Broker 间同步元数据。

但有个问题:如果 Broker 间通信断开(网络分区),可能出现多个节点都认为自己是主节点 的情况,导致数据不一致。这就是所谓的脑裂问题

打个比方:公司有三个办公室,平时通过内网通信。突然网络断了,每个办公室都以为自己是总部,各自做决策,等网络恢复后发现决策冲突了。

6.2 Quorum 队列的解决方案

RabbitMQ 3.8 版本引入了 Quorum 队列 ,使用 Raft 一致性算法来解决脑裂问题。

Raft 算法核心思想

  • 集群中只有一个 Leader,其他都是 Follower

  • 任何写操作必须经过多数节点(Quorum)确认才算成功

  • Leader 挂了,通过选举产生新 Leader

    ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
    │ Broker-1 │ │ Broker-2 │ │ Broker-3 │
    │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │
    │ │Q1 │ │ │ │Q1 │ │ │ │Q1 │ │
    │ │(Leader)│←────→│ (Follower)│←────→│ (Follower)│ │
    │ └───────┘ │ │ └───────┘ │ │ └───────┘ │
    └─────────────┘ └─────────────┘ └─────────────┘

    Raft 选举

写入流程

复制代码
1. 生产者发送消息到 Leader
2. Leader 将消息复制给 Follower
3. 超过半数节点确认后,Leader 返回成功
4. 如果 Leader 挂了,剩余节点选举新 Leader

6.3 为什么 Quorum 能解决脑裂

假设 3 个节点,网络分区后变成 1 + 2 两个分区:

  • 1 个节点的分区:无法获得多数票(需要 2 票),不能选出 Leader,停止服务
  • 2 个节点的分区:可以获得多数票,选出 Leader,继续服务

这样就保证了任何时刻最多只有一个 Leader,避免了脑裂。

6.4 Quorum 队列 vs 镜像队列

特性 镜像队列 Quorum 队列
一致性算法 无(简单同步) Raft
脑裂处理 可能脑裂 不会脑裂
数据一致性 最终一致 强一致
性能 较高 略低(需要多数确认)
推荐场景 对一致性要求不高 对数据一致性要求高

七、集群模式对比与选型

7.1 三种模式对比

模式 高可用 高吞吐 数据一致性 复杂度
普通集群 -
镜像队列 最终一致
Quorum队列 强一致

7.2 选型建议

选普通集群

  • 对高可用要求不高
  • 追求高吞吐量
  • 消息丢失可以接受

选镜像队列

  • 需要高可用
  • 对数据一致性要求不是特别严格
  • RabbitMQ 版本低于 3.8

选 Quorum 队列

  • 需要高可用
  • 对数据一致性要求高
  • RabbitMQ 版本 3.8+
  • 金融、支付等关键业务

7.3 RabbitMQ vs Kafka vs RocketMQ

特性 RabbitMQ Kafka RocketMQ
定位 企业级消息中间件 大数据流处理 业务消息中间件
协议 AMQP 自定义 自定义
优先级队列 ✅ 原生支持
延迟队列
死信队列
事务消息 ⚠️ 仅发送端
吞吐量 万级 十万级 十万级
适用场景 复杂路由、企业集成 日志、大数据 电商、金融业务

八、总结

本文介绍了 RabbitMQ 的核心概念和集群架构:

概念 说明
Queue 存储消息的队列,独立进程
Exchange 消息路由中心,根据规则分发消息
Broker RabbitMQ 实例
元数据 Exchange 里的路由规则和绑定关系

三种集群模式

模式 核心思想
普通集群 同步元数据,不同步队列数据,提升吞吐
镜像队列 队列数据多副本,牺牲吞吐换高可用
Quorum队列 Raft 算法,强一致性,解决脑裂

核心结论 :做架构,做到最后,都是在做折中。普通集群牺牲高可用换吞吐,镜像队列牺牲吞吐换高可用,没有完美的方案,只有适合的场景。


热门专栏推荐

等等等还有许多优秀的合集在主页等着大家的光顾,感谢大家的支持

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😊

希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🙏

如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🌟

相关推荐
独自归家的兔5 小时前
Spring Cloud核心架构组件深度解析(原理+实战+面试高频)
spring cloud·面试·架构
云上凯歌8 小时前
01 ruoyi-vue-pro框架架构剖析
前端·vue.js·架构
七夜zippoe9 小时前
事件驱动架构:构建高并发松耦合系统的Python实战
开发语言·python·架构·eda·事件驱动
狼爷11 小时前
高并发与分布式系统中的幂等处理
架构
小北方城市网11 小时前
第1课:架构设计核心认知|从0建立架构思维(架构系列入门课)
大数据·网络·数据结构·python·架构·数据库架构
职业码农NO.112 小时前
AI 技术栈完整解析,从 GPU 到应用的五层架构
人工智能·架构·系统架构·aigc·agent
云小逸12 小时前
【windows系统编程】第一章 Windows 系统核心架构与基础概念
windows·架构
川西胖墩墩12 小时前
团队协作泳道图制作工具 PC中文免费
大数据·论文阅读·人工智能·架构·流程图
码间拾光・菲林斯12 小时前
PostgreSQL 微服务架构开发实战:数据一致性、多租户设计与框架集成
微服务·postgresql·架构
Python_Study202512 小时前
企业级数据采集系统选型指南:从技术挑战到架构实践
架构