【MQ】RabbitMQ:架构、工作模式、高可用与流程解析

【MQ】RabbitMQ:架构、工作模式、高可用与流程解析

    • [一、RabbitMQ 整体结构](#一、RabbitMQ 整体结构)
    • [二、RabbitMQ 的 4 种工作模式](#二、RabbitMQ 的 4 种工作模式)
      • [1. Fanout 交换机:广播模式](#1. Fanout 交换机:广播模式)
      • [2. Direct 交换机:点对点模式](#2. Direct 交换机:点对点模式)
      • [3. Topic 交换机:通配符匹配模式](#3. Topic 交换机:通配符匹配模式)
      • [4. Headers 交换机:基于消息头匹配](#4. Headers 交换机:基于消息头匹配)
    • [三、RabbitMQ 的高可用](#三、RabbitMQ 的高可用)
      • [1. 普通集群](#1. 普通集群)
      • [2. 镜像集群](#2. 镜像集群)
    • [四、RabbitMQ 的数据分片](#四、RabbitMQ 的数据分片)
    • [五、RabbitMQ 的工作流程](#五、RabbitMQ 的工作流程)

一、RabbitMQ 整体结构

  • 生产者:发消息,把业务数据包成消息,通过网络发给 RabbitMQ 服务端(也就是 Broker)。

  • 消费者:收消息,和 Broker 连起来,订阅指定的队列,拿到消息后就去执行业务逻辑,比如处理订单、发通知。

  • Broker:可以理解成 RabbitMQ 本身 ------ 负责接生产者发的消息,把消息存到磁盘(可选),管着队列和交换机的关系,处理消费者要消息的请求。

二、RabbitMQ 的 4 种工作模式

Kafka也好,RocketMQ也好,他们都抽象出了一个Topic的概念,消息需要被发送到某个Topic下面,然后实际存储到某个队列里面,但是队列这个概念实际上是对用户屏蔽的,用户实际感知的其实是消息和Topic,但RabbitMQ的设计是完全不一样的。

RabbitMQ为了消息的灵活路由,设计了一个交换机,交换机通过绑定关系去和队列绑定,然后把消息转发到对应的队列,然后消费者去监听队列获取消息。

1. Fanout 交换机:广播模式

Fanout交换机把消息路由到这个交换机绑定的所有队列里面。

比如系统通知、日志同步,像把操作日志同时发到 "日志存储队列" 和 "日志告警队列",就适合用这个。

2. Direct 交换机:点对点模式

Direct交换机呢,就根据你发消息时的Routing Key,然后把消息路由到对应的Binding Key绑定的队列里面,这两个Key只要是一样的,它就给你路由到对应的队列里面,这个就是点对点的方式了。

比如用户下单后,"订单支付消息" 只发给 "订单处理队列",这种点对点的场景就用它。

3. Topic 交换机:通配符匹配模式

Topic交换机和Direct交换机差不多,但是绑定队列的时候可以用通配符,就更加灵活一点。

Binding Key 可以用两种通配符:

  • :匹配一个单词,比如 "order." 能匹配 "order.pay""order.refund",但匹配不了 "order.pay.success";

  • #:匹配零个或多个单词,比如 "order.#" 能匹配 "order.pay""order.pay.success"。

像按地区分的订单消息,把 "北京的订单" 转到 "order.beijing" 队列,"上海的订单" 转到 "order.shanghai" 队列,就适合用这个,灵活度高。

4. Headers 交换机:基于消息头匹配

Headers交换机它不靠 Routing Key 的匹配规则来路由消息,而是看消息头(Header)里的键值对 ------ 绑队列时定一组 Header 规则,只有消息头满足规则,才会转到这个队列。

但它用起来麻烦,性能还不好,实际开发里很少用,能被 Topic 替代。

三、RabbitMQ 的高可用

单节点的 RabbitMQ 有单点故障风险,一旦节点挂了,消息服务就断了。RabbitMQ 有两种集群模式,能解决高可用问题:

1. 普通集群

集群里所有节点会同步 "元数据",比如队列名、交换机类型、绑定关系这些,但消息只存在 "创建队列的节点" 上(叫 "队列主节点")。其他节点只存 "指向主节点的引用",不存消息本身。

优点是省存储空间,元数据同步不重;但缺点很明显 ------ 要是主节点挂了,这个队列的消息就没法用了,就算其他节点活着也没用,没法实现真的高可用。适合只需要分担连接压力,对消息可用性要求不高的场景。

2. 镜像集群

镜像集群就是说集群里面的每个节点,都会有这个队列的完整镜像。

就是可以部署一个主节点,然后部署几个镜像节点作为备份,读写都是主节点来处理,然后主节点同步给镜像节点。

这和Kafka的多副本机制基本上是类似的,相当于对队列做多个副本,你写消息到某个队列的时候,它就可以把这个消息自动同步到其他节点的队列上,其实就是一种多副本的机制,你也可以理解为是一种主从或者主备的机制。

优点是容灾能力强,能实现真高可用;但缺点是消息同步会增加网络开销,节点越多,同步压力越大。适合支付、订单这种对消息可用性要求高的核心业务。

四、RabbitMQ 的数据分片

如果业务数据量特别大,单节点存不下全量数据,就需要数据分片 ------ 把数据分到多个节点存。但 RabbitMQ原生不支持数据分片 ,得用官方提供的rabbit_sharding插件实现:

  1. 创建 "分片交换机"(插件提供的)和多个 "物理分片队列",这些物理队列会分到集群的不同节点;

  2. 配置分片策略,比如按 Routing Key 哈希、轮询;

  3. 生产者把消息发到分片交换机,插件按策略自动把消息转到不同节点的物理分片队列;

  4. 消费者订阅分片交换机,插件会协调消费者从不同物理队列拿消息。

数据分片的思路就是:一个节点存不了全量数据,那就让集群的每个节点只保存部分数据,然后通过负载均衡算法让请求路由到对应的节点。这和 MongoDB 的分片集群、Redis 的分片集群思路差不多。

五、RabbitMQ 的工作流程

RabbitMQ 的消息流转流程:

  1. 准备工作:先在 Broker 里创建交换机和队列,再用绑定键(Binding Key)把它们绑好;

  2. 生产者连 Broker:生产者通过 TCP 和 Broker 建立连接,创建信道(Channel)------ 复用连接能减少网络开销;

  3. 生产者发消息:指定交换机名称和 Routing Key,把消息发给交换机;

  4. 交换机路由消息:交换机按自己的类型(比如 Direct/Topic)和绑定规则,匹配 Routing Key 和 Binding Key,把消息转到对应的队列;

  5. 消息持久化:要是队列开了持久化,Broker 会把消息写到磁盘,防止节点挂了丢消息;

  6. 消费者消费消息:消费者和 Broker 连起来,订阅目标队列,拿到消息后执行业务逻辑,执行完给 Broker 发 "确认信号(Ack)",Broker 收到 Ack 就把队列里的这条消息删了。

相关推荐
骄马之死1 天前
SpringMVC + SpringBoot 核心知识点总结
java·spring boot·后端
刀法如飞1 天前
一文搞懂DDD 领域驱动设计思想原理
设计模式·架构·代码规范
郑洁文1 天前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
螺丝钉code1 天前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
giaz14n9X1 天前
Redis 分布式锁进阶第五十七篇
数据库·redis·分布式
Cosolar1 天前
LlamaIndex 文档解析与分块策略深度解析
人工智能·面试·架构
WyCAGy8ij1 天前
Redis 分布式锁进阶第二篇讲解
数据库·redis·分布式
摇滚侠1 天前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea
caimouse1 天前
Reactos 第 4 章 对象管理 — 4.5 几个常用的内核函数
c语言·windows·架构
VidDown1 天前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman