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

相关推荐
煎饼学大模型7 小时前
Agent 的“大脑-手“解耦架构:当推理层和工具执行层各自独立演进
数据库·人工智能·oracle·架构·agent
头发还在的女程序员7 小时前
医院陪诊管理系统怎么选择?——2026 年选型避坑与架构参考
java·开发语言·陪诊系统·陪诊app·医院陪诊陪护
CodeStats7 小时前
【Spring事务】Spring事务注解 @Transactional 完整体系:从 MySQL 隔离级别到 MyBatis 原理详解
java·spring·mybatis·事务·transactional
我命由我123458 小时前
Android 开发问题:为 PDFView 设置一个带有黑色边框的背景 drawable,但边框没有生效
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
都叫我大帅哥10 小时前
从Python到Java:为什么企业级Agent最终会选择Java?
java·ai编程
wanderist.10 小时前
Lambda表达式在算法竞赛中的应用
java·开发语言·算法
腻害兔12 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:IM 即时通讯模块,一个被低估的「全功能聊天系统」
java·前端·vue.js·产品经理·ai编程
心念枕惊12 小时前
.NET CORE 授权进阶-角色、策略与动态权限实现
java·前端·.netcore
余—笙13 小时前
Docker安装rabbitmq并安装延迟队列插件
docker·容器·rabbitmq
韩楚风13 小时前
【参天引擎】一次宕机后的数据恢复,让我把 Cantian 持久化与恢复的六大机制全搞明白了
服务器·网络·数据库·分布式·mysql·架构·cantian