【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 就把队列里的这条消息删了。

相关推荐
埃泽漫笔2 小时前
RabbitMQ为什么使用AMQP协议
rabbitmq
Porunarufu2 小时前
JAVA·类和对象③封装及包
java·开发语言
霍小毛3 小时前
Kubernetes云平台管理实战:滚动升级与秒级回滚
java·容器·kubernetes
代码充电宝3 小时前
LeetCode 算法题【简单】20. 有效的括号
java·算法·leetcode·面试·职场和发展
祈祷苍天赐我java之术3 小时前
Redis 的原子性操作
java·redis
wdfk_prog3 小时前
klist 迭代器初始化:klist_iter_init_node 与 klist_iter_init
java·前端·javascript
凸头3 小时前
Collections.synchronizedList()详解
java
用户0273851840263 小时前
【Android】MotionLayout详解
java·程序员
Jammingpro3 小时前
【Git版本控制】Git初识、安装、仓库初始化与仓库配置(含git init、git config与配置无法取消问题)
java·git·elasticsearch