当前位置: 首页 > article >正文

RabbitMQ仲裁队列高可用架构解析

#作者:闫乾苓

文章目录

  • 概述
  • 工作原理
    • 1.节点之间的交互
    • 2.消息复制
    • 3.共识机制
    • 4.选举领导者
    • 5.消息持久化
    • 6.自动故障转移
  • 集群环境
  • 节点管理
    • 仲裁队列增加集群节点
    • 重新平衡仲裁队列leader所在节点
    • 仲裁队列减少集群节点
  • 副本管理
    • add_member 在给定节点上添加仲裁队列成员(副本)
    • delete_member删除给定节点上的仲裁队列成员(副本)
  • 节点高可用测试

本文使用目前官方推荐的quorum 类型的队列如何进行高可用设置进行了测试及说明。

概述

仲裁队列是一种现代队列类型,它基于Raft 共识算法实现了持久的、复制的 FIFO 队列。

旨在更加安全,并提供更简单、定义明确的故障处理语义,用户在设计和操作系统时应该更容易推理。

仲裁队列和流现在取代了原始的、复制的镜像经典队列。镜像经典队列早已被弃用,并已从 RabbitMQ 4.x 中删除。

仲裁队列针对数据安全是首要任务的用例进行了优化。仲裁队列应被视为复制队列类型的默认选项。

工作原理

RabbitMQ的仲裁队列通过使用Raft一致性算法、消息复制和持久化等技术,实现了高可用性的消息传输和数据存储。这些机制共同确保了即使在节点故障或网络异常等不利情况下,消息仍然能够可靠地传输和存储

1.节点之间的交互

在RabbitMQ的集群中,节点之间通过交换消息来进行状态同步。当一个新节点加入或发生故障转移时,其他节点会与该节点进行交互,以确保其状态与集群保持同步。

2.消息复制

RabbitMQ使用消息复制技术来确保消息在集群中的可靠存储。每个消息都会被复制到多个节点上,以防止在某些节点发生故障时数据丢失。这种复制机制为数据的高可用性提供了保障。

3.共识机制

RabbitMQ的仲裁队列使用Raft一致性算法来实现共识机制。Raft是一种用于管理复制日志的一致性算法,它通过在集群中的节点之间达成共识来确保消息的可靠传输。当一个节点发送一条消息时,其他节点会验证该消息的一致性,并确保其在整个集群中可靠传输。

4.选举领导者

在RabbitMQ的仲裁队列中,存在一个领导者节点和一个或多个副节点。领导者节点负责处理写请求,而副节点则复制领导者的操作。当领导者节点发生故障时,副节点会通过Raft算法进行选举,以选出一个新的领导者节点来继续处理写请求。

5.消息持久化

RabbitMQ中的仲裁队列支持消息持久化,这意味着即使在节点重启或崩溃的情况下,消息也不会丢失。通过将消息写入磁盘并在副节点之间进行复制,仲裁队列确保了消息的长期保存和可靠性。

6.自动故障转移

如果领导者节点发生故障,RabbitMQ会自动将一个副节点提升为新的领导者节点。其他副节点则会与新的领导者节点进行同步,以确保集群的可用性和数据的一致性。这种自动故障转移机制进一步提高了RabbitMQ仲裁队列的高可用性。

集群环境

Rabbimq集群使用RabbitMQ Cluster Kubernetes Operator部署,使用nfs storageClass的pvc进行持久化存储。

apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:name: rabbitmq-cluster01namespace: rabbitmq-test
spec:replicas: 3image: rabbitmq:3.13.7-managementresources:requests:cpu: 500mmemory: 1Gilimits:cpu: 2000mmemory: 4Girabbitmq:additionalConfig: |cluster_partition_handling = pause_minoritydisk_free_limit.relative = 1.0collect_statistics_interval = 10000channel_max = 1000vm_memory_high_watermark_paging_ratio = 0.7total_memory_available_override_value = 4GBlog.file = /var/log/rabbitmq/rabbit.logpersistence:storageClassName: nfsstorage: "20Gi"affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: app.kubernetes.io/nameoperator: Invalues:- rabbitmq-cluster01topologyKey: kubernetes.io/hostnameservice:type: NodePort

节点管理

仲裁队列增加集群节点

通过在指定节点上为所有匹配的队列添加成员(副本)来增长仲裁队列集群。

rabbitmq-queues [--node <node>] [--longnames] [--quiet] grow <node> <all | even> [--vhost-pattern <pattern>] [--queue-pattern <pattern>] [--membership <promotable|voter>]
<--node> 
用于放置副本的节点名称
<all | even> 
为所有匹配的队列或仅为成员计数为偶数的队列添加成员
--queue-pattern 
用于匹配队列名称的正则表达式
--vhost
匹配虚拟主机名的正则表达式
--membership
添加可晋升的非投票人(默认)或正式投票人
--errors-only
仅列出报告错误的队列

为所有匹配的队列,vhost为/,匹配所有queue 增加‘rbt04’副本节点

rabbitmq-queues grow "rabbit@rbt04" "all" --vhost-pattern "/" --queue-pattern ".*"

在这里插入图片描述
在这里插入图片描述
仅为副本数为偶数的队列,vhost为/,匹配所有queue, 增加‘rbt05’副本节点
在这里插入图片描述

[root@rbt01 ~]# rabbitmq-queues grow "rabbit@rbt05" "even" --vhost-pattern "/" --queue-pattern 
".*"

因使用了even参数,只匹配了偶数节点的queue-quorum-02
在这里插入图片描述
在这里插入图片描述

重新平衡仲裁队列leader所在节点

在正在运行的集群节点之间重新平衡复制队列的领导者
用法:

rabbitmq-queues [--node <node>] [--longnames] [--quiet] rebalance < all | classic | quorum | stream > [--vhost-pattern <pattern>] [--queue-pattern <pattern>]
<type>队列类型,必须是以下之一:all、classic、quorum、stream
--queue-pattern <pattern>用于匹配队列名称的正则表达式
--vhost-pattern <pattern>匹配虚拟主机名的正则表达式

在这里插入图片描述
对vhost /下,所有的queue,进行重新平衡leader

[root@rbt01 ~]#  rabbitmq-queues rebalance "all" --vhost-pattern "/" --queue-pattern ".*"

重新平衡后,3个队列的leader 由原来的全部为rbt01,变成了rbt01,rbt03,rbt04
在这里插入图片描述

仲裁队列减少集群节点

用法:

rabbitmq-queues [--node <node>] [--longnames] [--quiet] shrink <node> [--errors-only]
<node>从中删除副本的节点名称
--errors-only仅列出报告错误的队列
[root@rbt01 ~]# rabbitmq-queues shrink rabbit@rbt04
Shrinking quorum queues on rabbit@rbt04...
vhost   name    size    result
/       queue-quorum-03 2       ok
/       queue-quorum-01 4       ok
/       queue-quorum-02 4       ok[root@rbt01 ~]# rabbitmq-queues shrink rabbit@rbt05
Shrinking quorum queues on rabbit@rbt05...
vhost   name    size    result
/       queue-quorum-01 3       ok
/       queue-quorum-02 3       ok

副本管理

声明仲裁队列时,必须在集群中启动其初始副本数。默认情况下,要启动的副本数最多为三个,集群中每个 RabbitMQ 节点一个。
三个节点是仲裁队列的实际最小副本数。在节点数较多的 RabbitMQ 集群中,添加比仲裁更多的副本不会在仲裁队列可用性方面带来任何改进,但会消耗更多集群资源。
因此,仲裁队列的推荐副本数是群集节点的仲裁数(但不少于三个)。这假设一个完整的群集至少有三个节点。

仲裁队列的副本由管理员管理。当新节点添加到集群时,它将不托管仲裁队列副本,除非管理员明确将其添加到仲裁队列或仲裁队列集的成员(副本)列表中。
当需要退役节点(从集群中永久删除)时,必须将其从其当前托管副本的所有仲裁队列的成员列表中明确删除。
为了成功添加和删除成员,集群中必须有一定数量的副本,因为集群成员资格的更改被视为队列状态的更改。
在执行涉及成员资格变更的维护操作时,需要小心不要因失去法定人数而意外导致队列不可用。
更换集群节点时,先添加新节点然后再退役其替换的节点是更安全的做法。

用于队列(尤其是仲裁队列)的维护任务, 管理复制队列的副本

add_member 在给定节点上添加仲裁队列成员(副本)

在这里插入图片描述

rabbitmq-queues add_member --vhost / queue-quorum-01 rabbit@rbt04
rabbitmq-queues add_member --vhost / queue-quorum-01 rabbit@rbt05

在这里插入图片描述

delete_member删除给定节点上的仲裁队列成员(副本)

rabbitmq-queues delete_member --vhost / queue-quorum-01 rabbit@rbt01
rabbitmq-queues delete_member --vhost / queue-quorum-01 rabbit@rbt02

在这里插入图片描述

节点高可用测试

创建queue

rabbitmqadmin declare queue name=queue_quorum_01 durable=true arguments='{"x-queue-type": "quorum"}'

创建exchange及bingding

rabbitmqadmin  declare exchange name=exchange_quorum_01 type=direct durable=true
rabbitmqadmin declare binding source=exchange_quorum_01 destination=queue_quorum_01 routing_key=queue_quorum_01

查看创建的queue_quorum_01的状态
在这里插入图片描述
查看exchange是否创建成功
在这里插入图片描述
通过python脚本写入10000条消息数据。
在这里插入图片描述
手动删除1个pod节点,模拟3节点集群中1个节点宕机的故障,数据不会丢失。
在这里插入图片描述
继续在producer客户端和cunsume 客户端python脚本一直时运行时,进行删除pod节点测试。
在这里插入图片描述
只要客户端连接的不是被停止的pod节点,客户端生产和消费都是正常的。通过web管理界面看,队列的状态是:running
在这里插入图片描述
此时如果继续删除第2个pod节点,模拟3节点集群中2个节点宕机的故障,在k8s中使用operator部署的RabbitMQ集群,在手动执行删除第2个pod是,命令将被挂起(无反应)直到operator通过内容部控制机制将第1个删除的pod重启成功,才会继续执行第2个pod的删除操作。
此时Rabbimq服务是正常状态(如果客户端连接的是被删除pod节点,连接会被断开,重连后连接被svc 负载到其他pod节点,可以正常读写数据)。这应该是RabbitMQ operator控制的效果,在3节点的集群中,确保同时只能1个pod节点宕机,服务不受影响。
在这里插入图片描述
在此期间,消息队列中的数据不会丢失。

另外在裸金属部署的3节点RabbitMQ集群中进行了类似测试,使用“rabbitmq stop_app”同时停止2个节点(非读写客户端正在连接的节点),此时RabbitMQ处于“minority”(少数)状态,这正是quorum队列需要超过半数节点正常才能正常工作的工作机制。
在这里插入图片描述
此时,写客户端(producer)的连接状态虽然为‘running’但实际测试是没有数据写入到服务器,读客户端(consumer)的连接状态为“flow”,也不能从服务器获取数据。
在这里插入图片描述

相关文章:

RabbitMQ仲裁队列高可用架构解析

#作者&#xff1a;闫乾苓 文章目录 概述工作原理1.节点之间的交互2.消息复制3.共识机制4.选举领导者5.消息持久化6.自动故障转移 集群环境节点管理仲裁队列增加集群节点重新平衡仲裁队列leader所在节点仲裁队列减少集群节点 副本管理add_member 在给定节点上添加仲裁队列成员&…...

刚出炉热乎的。UniApp X 封装 uni.request

HBuilder X v4.66 当前最新版本 由于 uniapp x 使用的是自己包装的 ts 语言 uts。目前语言还没有稳定下来&#xff0c;各种不支持 ts 各种报错各种不兼容问题。我一个个问题调通的&#xff0c;代码如下&#xff1a; 封装方法 // my-app/utils/request.uts const UNI_APP_BASE…...

Apache Kafka 实现原理深度解析:生产、存储与消费全流程

Apache Kafka 实现原理深度解析&#xff1a;生产、存储与消费全流程 引言 Apache Kafka 作为分布式流处理平台的核心&#xff0c;其高吞吐、低延迟、持久化存储的设计使其成为现代数据管道的事实标准。本文将从消息生产、持久化存储、消息消费三个阶段拆解 Kafka 的核心实现原…...

Python 训练营打卡 Day 41

简单CNN 一、数据预处理 在图像数据预处理环节&#xff0c;为提升数据多样性&#xff0c;可采用数据增强&#xff08;数据增广&#xff09;策略。该策略通常不改变单次训练的样本总数&#xff0c;而是通过对现有图像进行多样化变换&#xff0c;使每次训练输入的样本呈现更丰富…...

leetcode付费题 353. 贪吃蛇游戏解题思路

贪吃蛇游戏试玩:https://patorjk.com/games/snake/ 问题描述 设计一个贪吃蛇游戏,要求实现以下功能: 初始化游戏:给定网格宽度、高度和食物位置序列移动操作:根据指令(上、下、左、右)移动蛇头规则: 蛇头碰到边界或自身身体时游戏结束(返回-1)吃到食物时蛇身长度增加…...

CCPC dongbei 2025 I

题目链接&#xff1a;https://codeforces.com/gym/105924 题目背景&#xff1a; 给定一个二分图&#xff0c;左图编号 1 ~ n&#xff0c;右图 n 1 ~ 2n&#xff0c;左图的每个城市都会与右图的某个城市犯冲&#xff08;每个城市都只与一个城市犯冲&#xff09;&#xff0c;除…...

系统性学习C语言-第十三讲-深入理解指针(3)

系统性学习C语言-第十三讲-深入理解指针&#xff08;3&#xff09; 1. 数组名的理解2. 使用指针访问数组3. ⼀维数组传参的本质4. 冒泡排序5. ⼆级指针 6. 指针数组7. 指针数组模拟二维数组 1. 数组名的理解 在上⼀个章节我们在使用指针访问数组的内容时&#xff0c;有这样的代…...

代理模式核心概念

代理模式核心概念 代理模式是一种结构型设计模式&#xff0c;通过创建一个代理对象来控制对原始对象的访问。主要分为两类&#xff1a; 一、静态代理 (Static Proxy) 定义&#xff1a;在编译期确定代理关系的模式&#xff0c;代理类和目标类都需要实现相同的接口。 核心特点…...

uni-app学习笔记十五-vue3页面生命周期(二)

onShow&#xff1a;用于监听页面显示&#xff0c;页面每次出现在屏幕上都触发&#xff0c;包括从下级页面点返回露出当前页面&#xff1b; onHide:监听页面隐藏&#xff0c;当离开当前页面时触发。 示例代码&#xff1a; <template><view>姓名&#xff1a;{{nam…...

贪心算法实战篇2

文章目录 前言序列问题摆动序列单调递增的数字 贪心解决股票问题买卖股票的最佳时机II 两个维度权衡问题分发糖果根据身高重建队列 前言 今天继续带大家进行贪心算法的实战篇2&#xff0c;本章注意来解答一些运用贪心算法的中等的问题&#xff0c;大家好好体会&#xff0c;怎么…...

Java 大视界 -- Java 大数据机器学习模型在元宇宙虚拟场景智能交互中的关键技术(239)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

Flask中关于app.url_map属性的用法

目录 一、app.url_map 是什么? 二、可以查看哪些信息? 三、示例:打印所有路由 四、结合 url_for() 使用 五、常见用途场景 六、结合 Flask CLI 使用 总结 app.url_map 是 Flask 中非常重要的一个属性,用于查看或操作整个应用的 URL 路由映射表(routing map)。它展…...

高速串行接口

1.网口设计方案 上图中给出了两种网口设计方案&#xff0c;最上面是传统设计方式&#xff0c;下面是利用GT作为PHY层的设计&#xff0c;然后FPGA中设计协议层和MAC层。 2.SRIO SRIO的本地操作和远程操作 3.其他高速接口 srio rapid io aurora8b10b aurora64b66b pcie s…...

学习STC51单片机23(芯片为STC89C52RCRC)

每日一言 成功的路上从不拥挤&#xff0c;因为坚持的人不多&#xff0c;你要做那个例外。 通过单片机发指令给ESP8266进行通信 通信原理(也是接线原理) 代码如下 代码解释一下&#xff0c;因为我们的指令是字符数组&#xff08;c语言没有字符串的概念&#xff09;&#xff0c;…...

一个完整的日志收集方案:Elasticsearch + Logstash + Kibana+Filebeat (一)

整体链路 [应用服务器] --> [Filebeat] --> [Logstash] --> [Elasticsearch] --> [Kibana] 组件职责 Kibana&#xff1a; 可视化和分析日志数据Elasticsearch&#xff1a; 存储和索引日志数据Logstash&#xff1a; 解析、转换和丰富日志数据Filebeat&#xff1a…...

网络系统中安全漏洞扫描为何重要?扫描啥?咋扫描?

在网络系统中&#xff0c;安全漏洞扫描占据着极其重要的位置&#xff0c;这一环节有助于我们发现并消除潜在的安全隐患&#xff0c;进而提高网络安全防护的等级。下面&#xff0c;我将对此进行详尽的说明。 基本概念 漏洞扫描技术可以揭示并评估网站存在的安全风险&#xff0…...

HiveSQL语法全解析与实战指南

Hive SQL完整语法体系与特性解析 一、数据定义语言&#xff08;DDL&#xff09; 库操作 CREATE DATABASE [IF NOT EXISTS] dbname[COMMENT 描述][LOCATION hdfs_path][WITH DBPROPERTIES (keyvalue)];ALTER DATABASE dbname SET DBPROPERTIES (keyvalue); DROP DATABASE [IF…...

【conda报错】InvalidArchiveError

InvalidArchiveError - conda - Conda Community Forum 还是pip安装吧...

Socket 编程 TCP

目录 1. TCP socket API 详解 1.1 socket 1.2 bind 1.3 listen 1.4 accept 1.5 read&&write 1.6 connect 1.7 recv 1.8 send 1.9 popen 1.10 fgets 2. EchoServer 3. 多线程远程命令执行 4. 引入线程池版本翻译 5. 验证TCP - windows作为client访问Linu…...

Redis-6.2.9 Sentinel 哨兵配置

目录 1 操作系统信息和redis软件版本 2 集群架构图 3 部署redis主从 4 sentinel 配置文件 5 运维管理 6 go编写应用业务测试 哨兵核心功能:能够后台监控redis主机是否故障&#xff0c;如果故障了根据投票自动将从库转换为主库 1 操作系统信息和redis软件版本 rootu24-re…...

基于TMC5160堵转检测技术的夹紧力控制系统设计与实现

点击下面图片带您领略全新的嵌入式学习路线 &#x1f525;爆款热榜 90万阅读 1.6万收藏 一、技术背景与系统原理 在工业自动化领域&#xff0c;夹紧力控制是精密装配、机床夹具等场景的核心需求。传统方案多采用压力传感器伺服电机的闭环控制方式&#xff0c;但存在系统复杂…...

从零开始搞个简易分布式部署环境

从零开始&#xff0c;意味着连个服务器都没有&#xff0c;所以第一步&#xff0c;随便上哪个顺眼的云厂家去租个便宜大碗的服务器&#xff08;不要window系统的就行&#xff09;&#xff0c;说大碗也不太对&#xff0c;主要是这碗能在手里用得久&#xff0c;这个就自己扒拉去了…...

XCTF-web-fileclude

解析如下 <?php include("flag.php"); // 包含敏感文件&#xff08;通常包含CTF挑战的flag&#xff09; highlight_file(__FILE__); // 高亮显示当前PHP文件源代码&#xff08;方便查看代码逻辑&#xff09;if(isset($_GET["file1"]…...

OpenShift AI - 启用过时版本的 Notebook 镜像

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在 OpenShift 4.18 OpenShift AI 2.19 的环境中验证 文章目录 查看可用 Notebook 镜像控制台查看命令行查看 Notebook 镜像、Image Stream 和 Image Registry Repository 对应关系启用老版本的 Notebook 镜…...

Redis 缓存穿透、缓存击穿、缓存雪崩详解与解决方案

在分布式系统中&#xff0c;Redis 凭借高性能和高并发处理能力&#xff0c;成为常用的缓存组件。然而&#xff0c;在实际应用中&#xff0c;缓存穿透、缓存击穿、缓存雪崩这三大问题会严重影响系统的性能与稳定性。本文将详细解析这三个问题的成因&#xff0c;并提供对应的解决…...

sass高阶应用

Sass(尤其是 SCSS 语法)除了基础功能外,还提供了许多高级特性,可以实现更灵活、可维护的样式系统。以下是 Sass 的 高级语法和应用技巧,适合中大型项目或组件库开发。 文章目录 一、控制指令(Control Directives)1. `@if / @else`2. `@for` 循环3. `@each` 遍历列表/Map…...

docker docker-ce docker.io

Ubuntu安装 ​​更新软件包列表​​ 首先确保软件包列表是最新的&#xff1a; sudo apt-get update 使用正确的卸载命令​​ 替换 docker-engine 为 docker-ce 或 docker.io&#xff1a; sudo apt-get remove docker docker-ce docker.io containerd runc ​​检查已安装的 Do…...

DQN和DDQN(进阶版)

来源&#xff1a; *《第五章 深度强化学习 Q网络》.ppt --周炜星、谢文杰 一、前言 Q表格、Q网络与策略函数 Q表格是有限的离散的&#xff0c;而神经网络可以是无限的。 对于动作有限的智能体来说&#xff0c;使用Q网络获得当下状态的对于每个动作的 状态-动作值 。那么 a…...

【组件】翻牌器效果

目录 效果组件代码背景素材 效果 组件代码 <template><divclass"card-flop":style"{height: typeof height number ? ${height}px : height,--box-width: typeof boxWidth number ? ${boxWidth}px : boxWidth,--box-height: typeof boxHeight nu…...

CentOS 7 环境中部署 LNMP(Linux + Nginx + MySQL 5.7 + PHP)

在 CentOS 7 环境中部署 LNMP&#xff08;Linux Nginx MySQL 5.7 PHP&#xff09; 环境的详细步骤如下。此方案确保各组件版本兼容&#xff0c;并提供完整的配置验证流程。 1. 更新系统 sudo yum update -y 2. 安装 MySQL 5.7 2.1 添加 MySQL 官方 YUM 仓库 由于MySQL并不…...