RabbitMQ 分布式高可用
文章目录
- 前言
- 一、持久化与内存管理
- 1、持久化机制
- 2、内存控制
- 1、命令行
- 2、配置文件
- 3、内存换页
- 4、磁盘控制
- 二、集群
- 1、Erlang的分布式特性
- 2、RabbitMQ的节点类型
- 2.1、磁盘节点 (Disk Node)
- 2.2、内存节点 (RAM Node)
- 3、构建集群
- 3.1 普通集群
- 3.2 镜像队列
- 3.3、高可用实现方案
- 3.3.1、选择节点
- 3.3.2、负载均衡
- 3.3.3、基于 HAproxy+Keepalived 搭建高可用
前言
RabbitMQ 的分布式高可用性(High Availability, HA)是通过多种机制和技术来确保消息传递系统的稳定性和可靠性,即使在部分组件或节点出现故障时也能持续提供服务。为了实现这一点,RabbitMQ 提供了集群配置、镜像队列、持久化以及负载均衡等多种手段
一、持久化与内存管理
1、持久化机制
RabbitMQ 的持久化分为消息持久化、队列持久化、交换器持久化。无论是持久化消息还是非持久化消息都可以被写入磁盘。
- 持久化消息,则会储存在内存中,同时也会写入磁盘
- 非持久化消息,则只会存在内存中

当内存使用达到 RabbitMQ 的临界值时,内存中的数据会被交换到磁盘,持久化消息由于本就存在于磁盘中,不会被重复写入。
消息的持久化是在发消息时,通过 deliveryMode 设置,队列、交换器也可以通过参数持久化,在单服务中,非持久化的消息、队列、交换器重启后会消失,即使内存换页写入磁盘了,也会消失。
2、内存控制
1、命令行
RabbitMQ 中通过内存阈值参数控制内存的使用量,当内存使用超过配置的阈值时,RabbitMQ 会阻塞客户端的连接并停止接收从客户端发来的消息,以免服务崩溃。
同时,会发出内存告警,此时客户端于与服务端的心跳检测也会失效。 当出现内存告警时,可以通过管理命令临时调整
rabbitmqctl set_vm_memory_high_watermark <fraction>
# rabbitmqctl set_vm_memory_high_watermark absolute <memory_limit>
- fraction, 为内存阈值,默认是0.4,建议 0.4~0.66,表示 RabbitMQ 使用的内存超过系统内存的40%时,会产生内存告警,
- memory_limit,代表大小,单位为 KB、MB、GB
这种方式修改,实时生效,重启后失效。
2、配置文件
可以通过修改配置文件的方式,使之永久生效,但是需要重启服务。
rabbitmq.conf
vm_memory_high_watermark.relative = 0.4
# 或者直接配置成大小
# vm_memory_high_watermark.absolute = "1GB"
RabbitMQ 提供 relative 与 absolute 两种配置方式
- relative:相对值,也就是前面的 fraction 参数,建议 0.4~0.66,不能太大
- absolute:绝对值,固定大小,单位为 KB、MB、GB
3、内存换页
除了定义高水位线外,还可以配置何时开始将队列内容分页到磁盘以释放内存。
默认情况下,当内存使用率达到高水位线的一半时,RabbitMQ就开始执行Paging操作。
可以通过修改vm_memory_high_watermark_paging_ratio来调整这一行为:
vm_memory_high_watermark_paging_ratio = 0.75
vm_memory_high_watermark.relative = 0.4
上述配置意味着在内存使用率达到 40% * 75% = 30% 时,RabbitMQ就会开始分页动作
当换页阈值vm_memory_high_watermark_paging_ratio大于 1 时,相当于禁用了换页功能
内存换页涉及到大量的I/O操作,因为数据必须从RAM转移到硬盘,并且在某些情况下还需要再次加载回内存,对性能有一定影响
4、磁盘控制
当RabbitMQ所在的服务器磁盘空间接近耗尽时,可能会导致服务不可用,因为此时操作系统可能无法创建新的文件或者写入现有文件。
为了避免这种情况发生,RabbitMQ提供了一套磁盘控制机制来监控可用磁盘空间,并在必要时采取预防措施。
配置磁盘阈值
可以通过命令行工具rabbitmqctl或者直接编辑配置文件来调整磁盘阈值。
- 命令行
rabbitmqctl set_disk_free_limit mem_relative 1.0
# 绝对值
rabbitmqctl set_disk_free_limit absolute 1GB
- 配置文件配置
disk_free_limit.relative = 1.0
# 绝对值
disk_free_limit.absolute = 1GB
一旦磁盘空间低于配置的阈值,RabbitMQ将停止接收新消息,并阻止基于内存的消息page到磁盘。这意味着直到有足够的空闲磁盘空间为止,所有的生产者都将被阻塞。
如果检测到磁盘空间不足,应该立即采取行动清理不必要的文件、归档旧日志或者扩展存储容量。此外,还可以考虑优化消息生产和消费的速度,减少未处理消息积压的可能性。
二、集群
RabbitMQ集群是一种通过多节点架构来提高消息传递系统可靠性和性能的技术,它允许在分布式环境中部署多个RabbitMQ实例,并让它们协同工作以提供更强大的服务
1、Erlang的分布式特性
RabbitMQ是基于Erlang语言开发的消息队列中间件,而Erlang本身具有很强的分布式能力,这使得RabbitMQ能够天然支持集群化部署。
Erlang通过同步各节点间的magic cookie(一种认证令牌)来实现节点之间的通信和识别。
服务的端口是 5672,UI 的端口是 15672,集群的端口是 25672。
需要注意的是, RabbitMQ 集群无法搭建在广域网上, 除非使用 federation 或者 shovel 等插件(没这个必要,在同一个机房做集群)。
2、RabbitMQ的节点类型
RabbitMQ的节点类型主要分为两种:磁盘节点(Disk Node)和内存节点(RAM Node)。这两种类型的节点在集群中扮演着不同的角色
2.1、磁盘节点 (Disk Node)
磁盘节点是将所有元数据持久化存储到磁盘上的节点。这意味着即使节点重启或发生故障,这些信息也不会丢失。
在单节点系统或者集群环境中,至少需要有一个磁盘节点来保证数据的持久性。磁盘节点确保了关键配置如队列、交换器、绑定关系、用户权限等不会因为服务中断而消失。
当集群中有新的节点加入或有旧节点离开时,必须通知至少一个磁盘节点以更新集群的状态。
2.2、内存节点 (RAM Node)
与磁盘节点不同,内存节点将所有的元数据存储在内存中而不是磁盘上。这使得内存节点能够提供更高的性能,因为内存访问速度远快于磁盘访问。 但是内存不是持久化的,如果节点重启,所有的数据都会丢失。
当有新的内存节点被添加到集群时,它会通知所有磁盘节点。内存节点唯一写入磁盘的信息就是集群中磁盘节点的地址, 只要它可以找到至少一个磁盘节点,就能在重启后重新加入集群。
注意:
如果 RabbitMQ 集群只有一个磁盘节点,然后磁盘节点挂了,可以正常的投递消息和消费消息,但是不能做以下事:
- 1、不能创建队列
- 2、不能创建交换机
- 3、不能创建用户绑定关系
- 4、不能修改用户权限
因此,在建立集群时应确保有两个或更多个磁盘节点,以便提高系统的可用性和可靠性。
# 加入集群时设置节点为内存节点
rabbitmqctl join_cluster --ram <existing_node_name>
# 从磁盘节点转换为内存节点
rabbitmqctl change_cluster_node_type disc | ram
3、构建集群
RabbitMQ 有两种集群模式:普通集群模式和镜像队列模式。
3.1 普通集群
普通集群模式下,不同的节点之间只会相互同步元数据(交换机、队列、绑定关系、Vhost 的定义),而不会同步消息。

队列 A 的消息只存储在节点 A 上。节点 B 和节点 C 只同步了队列 A 的定义,但是没有同步消息。
假如生产者连接的是节点 C,要将消息通过交换机 A 路由到队列 A,最终消息还是会转发到节点 A 上存储,因为队列 A 的内容只在节点 A 上。
同理,如果消费者连接是节点 B,要从队列 A 上拉取消息,消息会从节点 A 转发 到节点 B。其它节点起到一个路由的作用,类似于指针。
出于存储和同步数据的网络开销的考虑, 如果所有节点都存储相同的数据, 就无法达到线性地增加性能和存储容量的目的(堆机器),所以不会同步所有数据
如果需要保证队列的高可用性,就不能用这种集群模式了,因为节点失效将导致相关队列不可用。
3.2 镜像队列
镜像队列模式下,消息内容会在镜像节点间同步,可用性更高。不过也有一定的副作用,系统性能会降低,节点过多的情况下同步的代价比较大。

一旦集群建立,你可以创建镜像队列。例如,在任一节点上:
docker exec -it rabbit1 bash
# 将名称以ha开头的队列同步至所有节点:
rabbitmqctl set_policy ha-all "^ha.*" '{"ha-mode": "all"}'
# 将所有队列至少同步至两个节点:
rabbitmqctl set_policy ha-two "^.*" '{"ha-mode": "exactly", "ha-params": 2, "ha-sync-mode": "automatic"}'
也可以为特定队列设置镜像策略:
rabbitmqctl set_policy my-queue-policy 'my-queue' '{"ha-mode":"all"}'
查看镜像队列配置
# 在任意节点上查看相应的策略:
rabbitmqctl list_policies
Listing policies for vhost "/" ...
vhost name pattern apply-to definition priority
/ ha-all ^ha.* all {"ha-mode":"all"} 0
/ ha-two ^.* all {"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"} 0
我们也可以根据 web 页进行查看,也可以在 web 页上进行镜像队列的配置

3.3、高可用实现方案
3.3.1、选择节点
集群搭建成功后,如果有多个内存节点,那么生产者和消费者应该连接到哪个内存节点?
如果我们在客户端代码中,需要根据一定的策略来选择要使用的服务器,那每个地方都要修改,客户端的代码就会出现很多的重复,修改起来也比较麻烦。
如果需要升级,那维护量可想而知的复杂,不建议使用

3.3.2、负载均衡
所以需要一个负载均衡的组件(例如 HAProxy,LVS,Nignx),由负载的组件来做路由。这个时候,只需要连接到负载组件的 IP 地址就可以了。
如果这个负载的组件也挂了呢?那再加集群,再路由,这样就死循环了
我们应该需要这样一个组件:
- 1、它本身有路由(负载)功能,可以监控集群中节点的状态(比如监控 HAProxy), 如果某个节点出现异常或者发生故障,就把它剔除掉。
- 2、为了提高可用性, 它也可以部署多个服务, 但是只有一个自动选举出来的 MASTER 服务器(叫做主路由器),通过广播心跳消息实现。
- 3、MASTER 服务器对外提供一个虚拟 IP,提供各种网络功能。也就是谁抢占到 VIP, 就由谁对外提供网络服务。应用端只需要连接到这一个 IP 就行了。
这个组件就是 Keepalived,它具有 Load Balance 和 High Availability 的功能。它的协议为VRRP协议(虚拟路由冗余协议Virtual Router Redundancy Protocol)。

3.3.3、基于 HAproxy+Keepalived 搭建高可用

规划:
- 内存节点1:192.168.8.143
- 内存节点2:192.168.8.144
- 内存节点3:192.168.8.145
- 磁盘节点1:192.168.8.146
- 磁盘节点2:192.168.8.147
- VIP:192.172.8.10
应用
- 1、我们规划了三个内存节点,两个磁盘节点。内存节点之间通过镜像队列的方式同步数据。内存节点用来给应用访问,磁盘节点用来持久化元数据。
- 2、为了实现对三个内存节点的负载,我们安装了两个 HAProxy,监听两个 5672 和 15672 的端口。
- 3、安装两个 Keepalived,一主一备。 两个 Keepalived 抢占一个 VIP 192.172.8.10。 谁抢占到这个 VIP,应用就连接到谁,来执行对 MQ 的负载。
如果出现故障,我们分析一下是否能够实现高可用
- 我们的 Keepalived 挂了一个节点,没有影响, 因为 BACKUP 会变成 MASTER,抢占 VIP。
- HAProxy 挂了一个节点,没有影响,我们的 VIP 会自 动路由的可用的 HAProxy 服务。
- RabbitMQ 挂了一个节点,没有影响, 因为 HAProxy 会自动负载到可用的节点。
相关文章:
RabbitMQ 分布式高可用
文章目录 前言一、持久化与内存管理1、持久化机制2、内存控制1、命令行2、配置文件 3、内存换页4、磁盘控制 二、集群1、Erlang的分布式特性2、RabbitMQ的节点类型2.1、磁盘节点 (Disk Node)2.2、内存节点 (RAM Node) 3、构建集群3.1 普通集群3.2 镜像队列3.3、高可用实现方案3…...
海康工业相机 SDK对接 Hikvision
有C#基础的,可以参考下,直接上代码 BaseResult 来自于Nuget包,搜Rotion可以搜出来 LS.Standard.Data 海康的接口操作,要先引用相应的dll using MvCamCtrl.NET; using PCZD.Commons.Data.CameraModel; using PCZD.Data; using Sys…...
开发技巧,vue 中的动态组件的引用 component + is
在项目中很多时候有切换 tab 的场景,一般来说都是用 v-if 或者 v-show 然后根据各种条件来控制显示隐藏。 其实我们可以使用 vue 中的动态组件,也能实现这个效果 <!-- currentTab 改变时组件也改变 --> <component :is"currentTab"…...
MySQL 二进制安装(正式篇)
Author:Arsen Date:2025/01/24 官方参考文档:点击链接跳转 目录 规划下载安装管理FAQ 规划 OSMySQL Server Version备注CentOS 7.9 or Linux - Generic8.0.33(GNU libc) 2.17 下载 二进制包下载地址:https://downloads.mysql.…...
MongoDB 数据库备份和恢复全攻略
在当今数据驱动的时代,数据库的稳定运行和数据安全至关重要。MongoDB 作为一款流行的 NoSQL 数据库,以其灵活的文档模型和高扩展性备受青睐。然而,无论数据库多么强大,数据丢失的风险始终存在,因此掌握 MongoDB 的备份…...
K8S部署DevOps自动化运维平台
持续集成(CI) 持续集成强调开发人员提交了新代码之后,立刻自动的进行构建、(单元)测试。根据测试结果,我 们可以确定新代码和原有代码能否正确地集成在一起。持续集成过程中很重视自动化测试验证结果&#…...
工业相机 SDK 二次开发-Sherlock插件
本文介绍了 sherlock 连接相机时的插件使用。通过本套插件可连接海康的工业相机。 一.环境配置 1. 拷贝动态库 在用户安装 MVS 目录下按照如下路径 Development\ThirdPartyPlatformAdapter 找到目 录为 DalsaSherlock 的文件夹,根据 Sherlock 版本找到…...
分布式版本控制系统:Git
1 Git概述 Git官网:https://git-scm.com/ Git是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目Git易于学习,占地面积小,性能极快。它具有廉价的本地库、方便的暂存区域和多个工作流分支等特性…...
页高速缓存与缓冲区缓存的应用差异
页高速缓存(Page Cache)与缓冲区缓存(Buffer Cache)是计算机系统中用于提高数据访问性能的两种不同类型的缓存机制,它们的差异主要体现在以下几个方面: 缓存目的 页高速缓存:主要用于加速对磁…...
C语言编程笔记:文件处理的艺术
大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 本文目录 引言正文一、为什么要用文件二、文件的分…...
如何编写一个MyBatis插件?
大家好,我是锋哥。今天分享关于【Redis为什么这么快?】面试题。希望对大家有帮助; 如何编写一个MyBatis插件? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 编写 MyBatis 插件需要使用 MyBatis 提供的插件接口,MyBa…...
验证二叉搜索树(力扣98)
根据二叉搜索树的特性,我们使用中序遍历,保证节点按从小到大的顺序遍历。既然要验证,就是看在中序遍历的条件下,各个节点的大小关系是否符合二叉搜索树的特性。双指针法和适合解决这个问题,一个指针指向当前节点&#…...
C语言初阶牛客网刷题—— HJ34 图片整理【难度:中等】
1. 题目描述 牛客网在线OJ链接 Lily上课时使用字母数字图片教小朋友们学习英语单词,每次都需要把这些图片按照大小(ASCII码值从小到大)排列收好。请大家给Lily帮忙,通过C语言解决。 输入描述:Lily使用的图片包括 “A…...
Golang Gin系列-7:认证和授权
在本章中,我们将探讨Gin框架中身份验证和授权的基本方面。这包括实现基本的和基于令牌的身份验证,使用基于角色的访问控制,应用中间件进行授权,以及使用HTTPS和漏洞防护保护应用程序。 实现身份认证 Basic 认证 Basic 认证是内置…...
mysql create table的用法
在MySQL中创建表的基本语法如下: CREATE TABLE table_name (column1 datatype,column2 datatype,column3 datatype,... );这里是一个例子,假设我们要创建一个名为employees的表,包含以下字段: id:一个整数类型的主键…...
蓝桥杯算法赛第25场月赛
前言 这些题对于我的难度有点大,大家感兴趣的可以来做一下,看一下,下面给大家展示一下题目 1. 桃花运走向【算法赛】 问题描述 2025 年春节,小明和小红兴致勃勃地去庙会玩耍。庙会上,一个算命先生摆摊算命…...
从介词到状语 (什么都研究一点系列)
契子 英语中介词的使用频率很高, 但在使用时本质上作为状语而成为句子成分, 没错 “本质上” 这三个字就是状语 😃 形式上是这样: 介词 -> 状语 -> 句子 常见的介词: 时间 at, 地点 on, 原因 of, 方式 in, 伴随 with, 比较 than, 条件 if 等等 下面我们开…...
CVE-2025-0411 7-zip 漏洞复现
文章目录 免责申明漏洞描述影响版本漏洞poc漏洞复现修复建议 免责申明 本文章仅供学习与交流,请勿用于非法用途,均由使用者本人负责,文章作者不为此承担任何责任 漏洞描述 此漏洞 (CVSS SCORE 7.0) 允许远程攻击者绕…...
java入门笔记基础语法篇(4)
变量 在Java中,每个变量都有一个类型(type)。在声明变量时,变量的类型位于变量 名之前。例如: int days; double salary; long earthPopulation; boolean done; 在Java中,每个声明以分号结束。变量名必须…...
学习数据结构(1)时间复杂度
1.数据结构和算法 (1)数据结构是计算机存储、组织数据的方式,指相互之间存在⼀种或多种特定关系的数据元素的集合 (2)算法就是定义良好的计算过程,取一个或一组的值为输入,并产生出一个或一组…...
存储基础 -- SCSI命令格式与使用场景
SCSI命令格式与使用场景 1. SCSI命令描述符块(CDB) 1.1 CDB基本概念 SCSI命令通过**命令描述符块(CDB, Command Descriptor Block)**表示。 CDB长度:SCSI命令根据使用场景有不同长度的CDB,常见的有6字节…...
PyTorch广告点击率预测(CTR)利用深度学习提升广告效果
目录 广告点击率预测问题数据集结构广告点击率预测模型的构建1. 数据集准备2. 构建数据加载器3. 构建深度学习模型4. 训练与评估 总结 广告点击率预测(CTR,Click-Through Rate Prediction)是在线广告领域中的重要任务,它帮助广告平…...
算法每日双题精讲 —— 二分查找(寻找旋转排序数组中的最小值,点名)
🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 别再犹豫了!快来订阅我们的算法每日双题精讲专栏,一起踏上算法学习的精彩之旅吧💪 在算法的…...
Flutter TextPainter 计算文本高度和行数
在开发中有的时候需要去计算文本的高度或者行数,从而控制展示的内容,比如进一步设置展示控件的高度,或者根据行数进行不同的内容展示。 在原生 Android 开发时,View 的绘制流程分为 measure,layout,draw 三…...
STM32-时钟树
STM32-时钟树 时钟 时钟...
算法知识补充2
一部分:Tire树:高效地存储和查找字符串集合的数据结构acwing835 #include<iostream> #include<cstring> using namespace std; const int N100010; int son[N][26],cnt[N],idx; char str[N]; void insert(char str[]){int p0;for(int i0;st…...
微信小程序-点餐(美食屋)02开发实践
目录 概要 整体架构流程 (一)用户注册与登录 (二)菜品浏览与点餐 (三)订单管理 (四)后台管理 部分代码展示 1.index.wxml 2.list.wxml 3.checkout.wxml 4.detail.wxml 小结优点 概要…...
WPF基础 | WPF 常用控件实战:Button、TextBox 等的基础应用
WPF基础 | WPF 常用控件实战:Button、TextBox 等的基础应用 一、前言二、Button 控件基础2.1 Button 的基本定义与显示2.2 按钮样式设置2.3 按钮大小与布局 三、Button 的交互功能3.1 点击事件处理3.2 鼠标悬停与离开效果3.3 按钮禁用与启用 四、TextBox 控件基础4.…...
CentOS7使用源码安装PHP8教程整理
CentOS7使用源码安装PHP8教程整理 下载安装包解压下载的php tar源码包安装所需的一些依赖扩展库安装前的配置修改配置文件1、进入php8的安装包 配置环境变量开机自启启动服务创建软连接常见问题1、checking for icu-uc > 50.1 icu-io icu-i18n... no2、configure: error: Pa…...
强化学习 - 基于策略搜索和策略优化: 高斯策略
最近在做毕设需要用强化学习来做控制,对强化学习的知识点做一下总结。 高斯策略 高斯策略属于强化学习中的基于策略优化的分支(Policy Optimization),尤其是策略梯度方法(Policy Gradient Methods) 的一部…...
