RabbitMQ 高可用方案:原理、构建与运维全解析

文章目录

  • 前言:
  • 1 集群方案的原理
  • 2 RabbitMQ高可用集群相关概念
    • 2.1 设计集群的目的
    • 2.2 集群配置方式
    • 2.3 节点类型
  • 3 集群架构
    • 3.1 为什么使用集群
    • 3.2 集群的特点
    • 3.3 集群异常处理
    • 3.4 普通集群模式
    • 3.5 镜像集群模式

前言:

在实际生产中,RabbitMQ 常以集群方案部署。因选用它做消息队列中间件时,了解集群原理对后续系统构建优化很关键。

一般若只为学习 RabbitMQ 运作,或核实业务工程逻辑正误,像确保业务流程连贯无差错,在本地或测试环境用单实例部署即可,能满足熟悉操作、排查初步问题等需求。

不过,鉴于消息队列中间件自身对于可靠性、并发性、吞吐量以及应对消息堆积能力等诸多关键性能指标有着严格要求,当进入生产环境时,从保障系统稳定高效运行的角度出发,一般都会优先考虑运用 RabbitMQ 的集群方案,以此确保在高负载、复杂多变的实际工况下,RabbitMQ 依然能够可靠地发挥其消息传递的核心功能,为整个分布式系统提供坚实的支撑。

1 集群方案的原理

RabbitMQ这款消息队列中间件产品本身是基于Erlang编写,Erlang语言天生具备分布式特性(通过同步Erlang集群各节点的Erlang Cookie来实现)。因此,RabbitMQ天然支持Cluster。这使得RabbitMQ本身不需要像ActiveMQ、Kafka那样通过ZooKeeper分别来实现HA方案和保存集群的元数据。集群是保证可靠性的一种方式,同时可以通过水平扩展以达到增加消息吞吐量能力的目的。
在这里插入图片描述

2 RabbitMQ高可用集群相关概念

2.1 设计集群的目的

  • 允许消费者和生产者在 RabbitMQ 个别
  • 节点崩溃的情况下继续运行。
  • 通过增加更多的节点来扩展消息通信的吞吐量。

2.2 集群配置方式

cluster:不支持跨网段,用于同一个网段内的局域网;可以随意的动态增加或者减少;节点之间需要运行相同版本的 RabbitMQ 和 Erlang。
federation:应用于广域网,允许单台服务器上的交换机或队列接收发布到另一台服务器上交换机或队列的消息,可以是单独机器或集群。federation 队列类似于单向点对点连接,消息会在联盟队列之间转发任意次,直到被消费者接受。通常使用 federation 来连接 internet 上的中间服务器,用作订阅分发消息或工作队列。
shovel:连接方式与 federation 的连接方式类似,但它工作在更低层次。可以应用于广域网。

2.3 节点类型

节点的存储类型分为两种:

  • 磁盘节点
  • 内存节点
    磁盘节点就是配置信息和元信息存储在磁盘上,内存节点把这些信息存储在内存中,当然内存节点的性能是大大超越磁盘节点的。
    单节点系统必须是磁盘节点,否则每次你重启 RabbitMQ 之后所有的系统配置信息都会丢失。RabbitMQ 要求集群中至少有一个磁盘节点,当节点加入和离开集群时,必须通知磁盘节点。
    特殊异常:集群中唯一的磁盘节点崩溃了
    如果集群中的唯一一个磁盘节点,结果这个磁盘节点还崩溃了,那会发生什么情况?如果唯一磁盘的磁盘节点崩溃了,不能进行如下操作:
  • 不能创建队列
  • 不能创建交换器
  • 不能创建绑定
  • 不能添加用户
  • 不能更改权限
  • 不能添加和删除集群几点

假如说,集群中只有一个磁盘节点,而恰巧不巧这个磁盘节点服务崩溃了,那么对于集群来说,仍然可以继续接受或发送消息,但是不能进行创建队列、交换器、绑定关系、用户,以及更改权限、添加和删除节点的操作。在磁盘节点恢复之前是无法执行任何更改操作的。所以,在集群中至少要有两个磁盘节点或者更多。
内存节点重启后,会先连接到磁盘节点,拷贝当前集群的配置的元数据副本。当有内存节点添加到集群时,会通知集群所有的磁盘节点。内存节点唯一写入磁盘的元数据信息就是集群中是磁盘节点的地址。只要内存节点可以找到至少一个磁盘节点,那么就能在重启后加入集群。
为了保证集群的可靠性,或者不确定是使用磁盘节点还是内存节点时,建议全部选择磁盘节点。

总结:如果唯一磁盘的磁盘节点崩溃,集群是可以保持运行的,但你不能更改任何东西。
解决方案:在集群中设置两个磁盘节点,只要一个可以,你就能正常操作。

2.4Erlang Cookie
Erlang Cookie 是保证不同节点可以相互通信的密钥,要保证集群中的不同节点相互通信必须共享相同的 Erlang Cookie。具体的目录存放在/var/lib/rabbitmq/.erlang.cookie。
RabbitMQ 底层是通过 Erlang 架构来实现的,所以 rabbitmqctl 会启动 Erlang 节点,并基于 Erlang 节点来使用 Erlang 系统连接 RabbitMQ 节点,在连接过程中需要正确的 Erlang Cookie 和节点名称,Erlang 节点通过交换 Erlang Cookie 以获得认证。

3 集群架构

3.1 为什么使用集群

内建集群作为 RabbitMQ 最优秀的功能之一,它的作用有两个:

  1. 允许消费者和生产者在 Rabbit 节点崩溃的情况下继续运行;
  2. 通过增加节点来扩展 Rabbit 处理更多的消息,承载更多的业务量;

3.2 集群的特点

RabbitMQ 的集群是由多个节点组成的,但我们发现不是每个节点都有所有队列的完全拷贝。
为什么默认情况下 RabbitMQ 不将所有队列内容和状态复制到所有节点?

有两个原因:

  1. 存储空间——如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据。
  2. 性能——如果消息的发布需安全拷贝到每一个集群节点,那么新增节点对网络和磁盘负载都会有增加,这样违背了建立集群的初衷,新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟。
    所以其他非所有者节点只知道队列的元数据,和指向该队列节点的指针。

3.3 集群异常处理

根据节点不无安全拷贝的特性,当集群节点崩溃时,该节点队列和关联的绑定就都丢失了,附加在该队列的消费者丢失了其订阅的信息,那么怎么处理这个问题呢?

这个问题要分为两种情况:

  1. 消息已经进行了持久化,那么当节点恢复,消息也恢复了;
  2. 消息未持久化,可以使用下文要介绍的双活冗余队列,镜像队列保证消息的可靠性

3.4 普通集群模式

在这里插入图片描述
这个模式的意思就是在多台机器上启动多个 RabbitMQ 实例。类似的 master-slave 模式一样。但是创建的 queue,只会放在一个 master rabbtimq 实例上,其他实例都同步那个接收消息的 RabbitMQ 元数据。

在消费消息的时候,如果你连接到的 RabbitMQ 实例不是存放 queue 数据的实例,这个时候 RabbitMQ 就会从存放 queue 数据的实例上拉去数据,然后返回给客户端。
总的来说,这种方式有点麻烦,没有做到真正的分布式,每次消费者连接一个实例后拉取数据,如果连接到不是存放 queue 数据的实例,这个时候会造成额外的性能开销。如果从放 queue 的实例拉取,会导致单实例性能瓶颈。

如果放 queue 的实例宕机了,会导致其他实例无法拉取数据,这个集群都无法消费消息了,没有做到真正的高可用。

所以这个事儿就比较尴尬了,这就没有什么所谓的高可用性可言了,这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写操作。

3.5 镜像集群模式

在这里插入图片描述
镜像集群模式才是真正的 RabbitMQ 的高可用模式,跟普通集群模式不一样的是:创建的 queue 无论元数据还是 queue 里的消息都会存在于多个实例上,每次写消息到 queue 的时候,都会自动把消息到多个实例的 queue 里进行消息同步。
这样的话任何一个机器宕机了别的实例都可以用提供服务,这样就做到了真正的高可用了。

但是也存在着不好之处:

  • 性能开销过高,消息需要同步所有机器,会导致网络带宽压力和消耗很重
  • 扩展性低:无法解决某个 queue 数据量特别大的情况,导致 queue 无法线性拓展。就算加了机器,那个机器也会包含 queue 的所有数据,queue 的数据没有做到分布式存储。
    对于 RabbitMQ 的高可用一般的做法都是开启镜像集群模式,这样起码来说做到了高可用,一个节点宕机了,其他节点可以继续提供服务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/954346.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React Fiber框架中的Render渲染阶段——workLoop(performUnitOfWork【beginWork与completeWork】)

触发渲染过程——renderRoot renderRoot 是一个函数,用于触发渲染工作。它通常会调用并递归地执行一系列的渲染任务,直到完成整个更新过程。这个过程包括执行 Fiber 树中的 beginWork 和 completeWork,以及渲染新状态或 DOM。 function ren…

一体机cell服务器更换内存步骤

一体机cell服务器更换内存步骤: #1、确认grdidisk状态 cellcli -e list griddisk attribute name,asmmodestatus,asmdeactivationoutcome #2、offline griddisk cellcli -e alter griddisk all inactive #3、确认全部offline后进行关机操作 shutdown -h now #4、开…

uni-app编写微信小程序使用uni-popup搭配uni-popup-dialog组件在ios自动弹出键盘。

uni-popup-dialog 对话框 将 uni-popup 的type属性改为 dialog&#xff0c;并引入对应组件即可使用对话框 &#xff0c;该组件不支持单独使用 示例 <button click"open">打开弹窗</button> <uni-popup ref"popup" type"dialog"…

SYS_OP_MAP_NONNULL NULL的等值比较

无意在数据库中发现了这个操作SYS_OP_MAP_NONNULL。 SYS_OP_MAP_NONNULL应该不是数据库中的对象&#xff0c;因为在DBA_OBJECTS中根本找不到它&#xff0c;而在STANDARD和DBMS_STANDARD包中也找不到函数说明。 SQL> SELECT * 2 FROM DBA_OBJECTS 3 WHERE OBJECT_NAME…

基于Java的百度AOI数据解析与转换的实现方法

目录 前言 一、AOI数据结构简介 1、官网的实例接口 2、响应参数介绍 二、Java对AOI数据的解析 1、数据解析流程图 2、数据解析实现 3、AOI数据解析成果 三、总结 前言 在当今信息化社会&#xff0c;地理信息数据在城市规划、交通管理、商业选址等领域扮演着越来越重要的…

深度学习中的学习率调度器(scheduler)分析并作图查看各方法差异

文章目录 1. 指数衰减调度器&#xff08;Exponential Decay Scheduler&#xff09;工作原理适用场景实现示例 2. 余弦退火调度器&#xff08;Cosine Annealing Scheduler&#xff09;工作原理适用场景实现示例 3. 步长衰减调度器&#xff08;Step Decay Scheduler&#xff09;工…

IPSEC实验

实验要求 某小型企业为扩大网络规模&#xff0c;设立分公司&#xff0c;今日要求分公司能够访问主公司对应的资源&#xff0c;为此很是苦恼 为满足其跨区域访问对端网络的要求&#xff0c;现要求使用IPSEC搭建隧道使得分公司能够与主公司通讯 实验拓扑 该公司与分公司拓扑大…

[c语言日寄]精英怪:三子棋(tic-tac-toe)3命慢通[附免费源码]

哈喽盆友们&#xff0c;今天带来《c语言》游戏中[三子棋boss]速通教程&#xff01;我们的目标是一边编写博文&#xff0c;一边快速用c语言实现三子棋游戏。准备好瓜子&#xff0c;我们计时开始&#xff01; 前期规划 在速通中&#xff0c;我们必须要有清晰的前期规划&#xf…

TensorFlow DAY3: 高阶 API(Keras,Estimator)(完)

TensorFlow 作为深度学习框架&#xff0c;当然是为了帮助我们更便捷地构建神经网络。所以&#xff0c;本次实验将会了解如何使用 TensorFlow 来构建神经网络&#xff0c;并学会 TensorFlow 构建神经网络的重要函数和方法。 知识点 Keras 顺序模型Keras 函数模型Keras 模型存储…

数据结构(Java版)第九期:LinkedList与链表

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 目录 一、LinkedList的模拟实现 1.1. 头插法 1.2. 尾插法 1.3. 插入中间节点 1.4. 删除某个节点 1.5. 删除所有为key的元素 二、LinkedList的使用 2.1. 什么是LinkedList 2.2. LinkedList的使⽤ 三、…

ubuntu18.04开发环境下samba服务器的搭建

嵌入式linux的发展很快&#xff0c;最近准备在一个新项目上采用新一代的linux核心板&#xff0c;发现linux内核的版本已经更新到5.4以上甚至6.0以上&#xff1b;之前常用的linux内核版本是2.6.4&#xff0c;虽然在某些项目上还能用但是明显跟不上时代的步伐了&#xff0c;所以要…

【优先算法】滑动窗口--(结合例题讲解解题思路)(C++)

目录 1. 例题1&#xff1a;最大连续1的个数 1.1 解题思路 1.2代码实现 1.3 错误示范如下&#xff1a;我最开始写了一种&#xff0c;但是解答错误&#xff0c;请看&#xff0c;给大家做个参考 2. 将 x 减到 0 的最小操作数 2.1解题思路 2.2代码实现 1. 例题1&#xff…

数据结构二叉树-C语言

数据结构二叉树-C语言 1.树1.1树的概念与结构1.2树的相关术语1.3树的表示1.4树形结构实际运用场景 2.二叉树2.1概念与结构2.2特殊的二叉树2.2.1满二叉树2.2.2完全二叉树 2.3二叉树存储结构2.3.1顺序结构2.3.2链式结构 3.实现顺序结构的二叉树4.实现链式结构二叉树4.1前中后序遍…

Qt/C++进程间通信:QSharedMemory 使用详解(附演示Demo)

在开发跨进程应用程序时&#xff0c;进程间通信&#xff08;IPC&#xff09;是一个关键问题。Qt 框架提供了多种 IPC 技术&#xff0c;其中 QSharedMemory 是一种高效的共享内存方式&#xff0c;可以实现多个进程之间快速交换数据。本文将详细讲解 QSharedMemory 的概念、用法及…

【vue3项目使用 animate动画效果】

vue3项目使用 animate动画效果 前言一、下载或安装npm 安装 二、引入组件三、复制使用四、完整使用演示总结 前言 提示&#xff1a;干货篇&#xff0c;不废话&#xff0c;点赞收藏&#xff0c;用到会后好找藕~ 点击这里&#xff0c;直接看官网哦 &#x1f449; 官网地址&#…

Android 15应用适配指南:所有应用的行为变更

Android系统版本适配&#xff0c;一直是影响App上架Google Play非常重要的因素。 当前Google Play政策规定 新应用和应用更新 必须以 Android 14&#xff08;API 级别 34&#xff09;为目标平台&#xff0c;才能提交到Google Play。现有应用 必须以 Android 13&#xff08;AP…

qml TargetDirection详解

1、概述 TargetDirection是QML&#xff08;Qt Modeling Language&#xff09;中一个用于指定粒子系统中粒子移动方向的类型。它允许粒子朝向一个目标点移动&#xff0c;这个目标点可以是QML界面上的一个具体位置&#xff0c;也可以是另一个QML元素的中心。TargetDirection通常…

Linux C 使用ZBar库解析二维码和条形码

1. 编译zbar库 下载 zbar 库源码&#xff0c;这里需要注意下&#xff0c;如果识别的二维码中有中文的话&#xff0c;会出现乱码&#xff0c;一般二维码里中文为UTF-8编码&#xff0c;zbar会默认给你把UTF-8转换为ISO8859-1。有两种解决办法&#xff0c;一是自己再转换一下编码…

金融项目实战 06|Python实现接口自动化——日志、实名认证和开户接口

目录 一、日志封装及应用&#xff08;理解&#xff09; 二、认证开户接口脚本编写 1、代码编写 1️⃣api目录 2️⃣script目录 2、BeautifulSoup库 1️⃣简介及例子 2️⃣提取html数据工具封装 3、认证开户参数化 一、日志封装及应用&#xff08;理解&#xff09; &…

基于springboot+vue+微信小程序的宠物领养系统

基于springbootvue微信小程序的宠物领养系统 一、介绍 本项目利用SpringBoot、Vue和微信小程序技术&#xff0c;构建了一个宠物领养系统。 本系统的设计分为两个层面&#xff0c;分别为管理层面与用户层面&#xff0c;也就是管理者与用户&#xff0c;管理权限与用户权限是不…