RabbitMQ 仲裁队列 -- 解决 RabbitMQ 集群数据不同步的问题

news2025/1/27 23:29:26

1.问题情景

        当我们搭建了一个 RabbitMQ 集群后是存在问题的,也就是数据不同步.我们可以来看下是什么问题

1. 1 添加队列

①:选择虚拟机(需要保证操作⽤户对当前虚拟机有操作权限)

②:设置队列名称

③:持久化队列

④:指定队列所在主节点,其他为从节点分别以 rabbit 节点和 rabbit2 节点添加两个队列

1.2 添加之后,可以看到三个节点都有队列了

1.3 往 testQueue 队列中发送⼀条数据(从任⼀节点都可以)

1.4 发送之后,观察 3 个节点的队列中均有消息

1.5 关闭主节点

root@hcss-ecs-2618:~# rabbitmqctl -n rabbit stop_app #rabbit为节点名称 
Stopping rabbit application on node rabbit@hcss-ecs-2618 ...
root@hcss-ecs-2618:~# 

关闭后可以看到 rabbit2 和 rabbit3 没有该队列的数据了,但是另⼀个队列不受影响

        也就是说,这个数据只在主节点存在,从节点没有,如果关闭的是 rabbit2,那么 testQueue2 的数据会消失 如何解决这个问题呢,就需要引⼊咱们的"仲裁队列"

2.仲裁队列(Quorum Queues)

        RabbitMQ 的仲裁队列是⼀种基于 Raft ⼀致性算法实现的持久化、复制的 FIFO 队列.

        仲裁队列提供队列复制的能⼒,保障数据的⾼可⽤和安全性.使⽤仲裁队列可以在 RabbitMQ 节点间进⾏队列数据的复制,从⽽达到在⼀个节点宕机时,队列仍然可以提供服务的效果.

Quorum Queues | RabbitMQ官⽅⽂档:Quorum Queues | RabbitMQ

        仲裁队列是 RabbitMQ 3.8 版本最重要的改动.他是镜像队列的替代⽅案.在 RabbitMQ 3.8版本问世之前,镜像队列是实现数据⾼可⽤的唯⼀⼿段,但是它有⼀些设计上的缺陷,这也是 RabbitMQ 提供仲裁队列的原因.经典镜像队列已被弃⽤,并计划在将来版本中移除.

2.1 Raft 协议介绍

什么是 Raft?

        Raft 是⼀种⽤于管理和维护分布式系统⼀致性的协议,它是⼀种共识算法,旨在实现⾼可⽤性和数据的持久性. Raft 通过在节点间复制数据来保证分布式系统中的⼀致性,即使在节点故障的情况下也能保证数据不会丢失.

        在分布式系统中,为了消除单点提⾼系统可⽤性,通常会使⽤副本来进⾏容错,但这会带来另⼀个问题,即如何保证多个副本之间的⼀致性?

        共识算法( Consensus Algorithm )就是做这个事情的,它允许多个分布式节点就某个值或⼀系列值达成⼀致性协议.即使在⼀些节点发⽣故障,⽹络分区或其他问题的情况下,共识算法也能保证系统的⼀致性和数据的可靠性.

        常⻅的共识算法有:Paxos,Raft,Zab 等

• Paxos:⼀种经典的共识算法,⽤于解决分布式系统中的⼀致性问题.

• Raft:⼀种较新的共识算法,Paxos 不易实现, raft 是对 Paxos 算法的简化和改进,旨在易于理解和实现.

• Zab:ZooKeeper 使⽤的共识算法,基于 Paxos 算法.,⼤部分和 Raft 相同,主要区别是对于 Leader的任期,Raft 叫做 term,Zab 叫做 epoch,状态复制的过程中,raft 的⼼跳从 Leader 向 Follower 发送,⽽ ZAB 则相反.

• Gossip:Gossip 算法每个节点都是对等的,即没有⻆⾊之分.Gossip 算法中的每个节点都会将数据改动告诉其他节点(类似传⼋卦)

2.2 Raft 基本概念

        Raft 使⽤ Quorum 机制来实现共识和容错,我们对 Raft 集群的操作必须得到⼤多数(>N/2)节点

的同意才能提交

节点指的是分布式系统中的⼀个独⽴成员

        当我们向 Raft 集群发起⼀系列读写操作时,集群内部究竟发⽣了什么呢?我们先来简单了解⼀下.

        Raft 集群必须存在⼀个主节点(Leader),客户端向集群发起的所有操作都必须经由主节点处理.所以 Raft 核⼼算法中的第⼀部分就是选主( Leader election ).没有主节点集群就⽆法⼯作,先选出⼀个主节点,再考虑其它事情.

        主节点会负责接收客户端发过来的操作请求,将操作包装为⽇志同步给其它节点,在保证⼤部分节点都同步了本次操作后,就可以安全地给客户端回应响应了.这⼀部分⼯作在 Raft 核⼼算法中叫⽇志复制 (Log replication).

        因为主节点的责任⾮常⼤,所以只有符合条件的节点才可以当选主节点.为了保证集群对外展现的⼀致性,主节点在处理操作⽇志时,也⼀定要谨慎,这部分在 Raft 核⼼算法中叫安全性(Safety).

        Raft 算法将⼀致性问题分解为三个⼦问题:

Leader选举

⽇志复制

安全性.

下⾯我们详细介绍下 Raft 的选主过程.

2.2.1 选主(Leader election)

        选主(Leader election)就是在集群中抉择出⼀个主节点来负责⼀些特定的⼯作.在执⾏了选主过程后,集群中每个节点都会识别出⼀个特定的,唯⼀的节点作为 leader.

节点⻆⾊

在 Raft 算法中,每个节点都处于以下三种⻆⾊之⼀

        • Leader(领导者): 负责处理所有客户请求,并将这些请求作为⽇志项复制到所有 Follower .Leader 定期向所有 Follower 发送⼼跳消息, 以维持其领导者地位,防⽌ Follower进⼊选举过程.

        • Follower(跟随者):接收来⾃ Leader 的⽇志条⽬,并在本地应⽤这些条⽬.跟随者不直接处理客户请 求.

         • Candidate(候选者):当跟随者在⼀段时间内没有收到来⾃ Leader 的⼼跳消息时,它会变得不确定 Leader 是否仍然可⽤.在这种情况下,跟随者会转变⻆⾊成为 Candidate,并开始尝试通过投票过程 成为新的 Leader.

        在正常情况下,集群中只有⼀个 Leader,剩下的节点都是 follower,下图展⽰了这些状态和它们之间的转换关系

        可以看出所有节点在启动时,都是 follow 状态,在⼀段时间内如果没有收到来⾃ leader 的⼼跳,从 follower切换到 candidate,发起选举.如果收到多数派(majority)的投票(含⾃⼰的⼀票)则切换到 leader 状态.Leader ⼀般会⼀直⼯作直到它发⽣异常为⽌.

任期

        Raft 将时间划分成任意⻓度的任期(term).每⼀段任期从⼀次选举开始,在这个时候会有⼀个或者多个 candidate 尝试去成为 leader,在成功完成⼀次 leaderelection 之后,⼀个 leader 就会⼀直管理集群直到任期结束.在某些情况下,⼀次选举⽆法选出 leader,这个时候这个任期会以没有 leader ⽽结束(如下图t3).同时⼀个新的任期(包含⼀次新的选举)会很快重新开始

        Term 更像是⼀个逻辑时钟(logic clock)的作⽤,有了它,就可以发现哪些节点的状态已经过期.每⼀个节点都保存⼀个 current term,在通信时带上这个 term 的值.

        每⼀个节点都存储着⼀个当前任期号(current term number).该任期号会随着时间单调递增.节点之间通信的时候会交换当前任期号,如果⼀个节点的当前任期号⽐其他节点⼩,那么它就将⾃⼰的任期号 新为较⼤的那个值.如果⼀个 candidate 或者 leader 发现⾃⼰的任期号过期了,它就会⽴刻回到 follower 状态.如果⼀个节点接收了⼀个带着过期的任期号的请求,那么它会拒绝这次请求. Raft 算法中服务器节点之间采⽤ RPC 进⾏通信,主要有两类 RPC 请求:

• RequestVote RPCs:请求投票,由 candidate 在选举过程中发出

• AppendEntries RPCs: 追加条⽬,由 leader 发出,⽤来做⽇志复制和提供⼼跳机制

选举过程

        Raft 采⽤⼀种⼼跳机制来触发 leader 选举,当服务器启动的时候,都是 follow 状态.如果 follower 在 election timeout内没有收到来⾃ leader 的⼼跳(可能没有选出 leader ,也可能 leader 挂了,或者 leader 与  follower 之间⽹络故障),则会主动发起选举.

步骤如下:

1. 率先超时的节点(基本不会出现两个节点同时超时的情况,因为节点的超时时间是一定范围内的随机值,如果两个节点同时超时并得到了相同的票数,就会开始新一轮的计时,选举),⾃增当前任期号然后切换为 candidate 状态,并投⾃⼰⼀票

2. 以并⾏的⽅式发送⼀个 RequestVote RPCs 给集群中的其他服务器节点(企图得到它们的投票)

3. 等待其他节点的回复

在这个过程中,可能出现三种结果

a. 赢得选举,成为 Leader (包括⾃⼰的⼀票)

b. 其他节点赢得了选举,它⾃⾏切换到 follower

c. ⼀段时间内没有收到 majority 投票,保持 candidate 状态,重新发出选举

投票要求:

• 每⼀个服务器节点会按照先来先服务原则(first-come-first-served)只投给⼀个 candidate.

• 候选⼈知道的信息不能⽐⾃⼰的少

接下来对这三种情况进⾏说明:

        第⼀种情况:赢得了选举之后,新的 leader 会⽴刻给所有节点发消息,⼴⽽告之,避免其余节点触发新的选举.

        第⼆种情况:⽐如有三个节点 A ,B ,C。

        A,B 同时发起选举,⽽ A 的选举消息先到达 C ,C 给 A 投了⼀票,当 B 的消息到达 C 时,已经不能满⾜上⾯提到的第⼀个约束,即 C 不会给 B 投票,这时候 A 就胜出了.A 胜出之后,会给 B,C发⼼跳消息,节点 B 发现节点 A 的 term 不低于⾃⼰的 term, 知道有已经有 Leader 了,于是把⾃⼰转换成follower.

        第三种情况:没有任何节点获得 majority 投票.⽐如所有的 follower 同时变成 candidate,然后它们都将票投给⾃⼰,那这样就没有 candidate 能得到超过半数的投票了.当这种情况发⽣的时候,每个 candidate 都会进⾏⼀次超时响应,然后通过⾃增任期号来开启⼀轮新的选举,并启动另⼀轮的 RequestVote RPCs.如果没有额外的措施,这种⽆结果的投票可能会⽆限重复下去.

        为了解决上述问题,Raft 采⽤ 随机选举超时时间(randomized election timeouts)来确保很少产⽣⽆结果的投票,并且就算发⽣了也能很快地解决。为了防⽌选票⼀开始就被⽠分,选举超时时间是从⼀个固定的区间(⽐如,150-300ms)中随机选择。这样可以把服务器分散开来以确保在⼤多数情况下会只有⼀个服务器率先结束超时,那么这个时候,它就可以赢得选举并在其他服务器结束超时之前发送⼼跳。

Raft 动画演⽰在线地址:raft.github.io

3.Raft 协议下的消息复制

        每个仲裁队列都有多个副本,它包含⼀个主和多个从副本. replication factor 为 5 的仲裁队列将会有1个 主副本和 4 个从副本.每个副本都在不同的 RabbitMQ节点上

        客户端(⽣产者和消费者)只会与主副本进⾏交互,主副本再将这些命令复制到从副本.当主副本所在的节点下线,其中⼀个从副本会被选举成为主副本,继续提供服务

        消息复制和主副本选举的操作,需要超过半数的副本同意.当⽣产者发送⼀条消息,需要超过半数的队列副本都将消息写⼊磁盘以后才会向⽣产者进⾏确认,这意味着少部分⽐较慢的副本不会影响整个队列的性能.

4.仲裁队列的使用

4.1. 创建仲裁队列

下⾯讲述三种创建⽅式

1)使⽤ Spring 框架代码创建

@Bean("quorumQueue")
public Queue quorumQueue() {
 return QueueBuilder.durable("quorum_queue").quorum().build();
}

2) 使⽤ amqp-client 创建(RabbitMQ 提供的原生 SDK 命令)

Map<String, Object> param = new HashMap<>();
param.put("x-queue-type", "quorum");
channel.queueDeclare("quorum_queue",true,false,false,param);

3)使用管理平台创建

创建时选择 Type 为 Quorum,Node 指定了哪个结点的队列是主队列,其余结点的是副本队列

4.2. 创建后观察管理平台

        可以看到,对比普通队列,仲裁队列后⾯有⼀个+ 2 字样,代表这个队列有2个镜像节点

        仲裁队列默认的镜像数为 5,即⼀个主节点,4个从副本节点. 

        如果集群中节点数量少于 5,⽐如我们搭建了 3 个节点的集群,那么创建的仲裁队列就是 1 主 2 从.

        如果集群中的节点数⼤于 5 个的话,那么就只会在 5 个节点中创建出 1主 4 从.

点进去,可以看到队列详情

        可以看到:当有多个仲裁队列时,主副本和从副本会分布在集群的不同节点上,每个节点可以承载多个主副本和从副本.

4.3 接收/发送消息

仲裁队列发送接收消息和普通队列操作⼀样

4.4 宕机演示

1. 给仲裁队列 quorum_queue 发送消息

发送消息后,从各个结点都能看到加入的一条数据

2.停掉主队列所在的节点

        quorum_queue 主队列所在的节点在 rabbit@hcss-ecs-2618,停掉这台机器

root@hcss-ecs-2618:~# rabbitmqctl -n rabbit stop_app #rabbit为节点名称 
Stopping rabbit application on node rabbit@hcss-ecs-2618 ...
root@hcss-ecs-2618:~# 

        观察其他节点,可以看到 quorum_queue 队列的内容依然存在. 并且,因为主队列所在节点宕机了,quorum_queue 主队列从 rabbit@hcss-ecs-2618 转移到了 rabbit2@hcss-ecs-2618

队列详细信息:只剩下两个成员了

        仲裁队列,是 RabbitMQ 从 3.8.0 版本引⼊的新的队列类型,Quorum 相⽐ Classic 在分布式环境下对消息的可靠性保障更⾼.普通队列只会存放在集群中的⼀个节点上,虽然通过其它节点也可以访问普通队列 但是其它节点只是把请求转发到队列所在的节点进⾏操作.⼀旦队列所在节点宕机,队列中的消息就会丢失,因此普通集群只是提⾼了并发能⼒,并未实现⾼可⽤.仲裁队列可以极⼤的保障 RabbitMQ 集群对接的⾼可⽤.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

环境变量配置与问题解决

目录 方法 配置了还是运行不了想要的东西 解决方案 为什么 解决方案 方法 方法一&#xff1a;此电脑右击-属性-相关链接-高级系统设置-环境变量&#xff08;N&#xff09;-系统变量里面找到Path-三个确定】 方法二&#xff1a;winr cmd 黑框输入sysdm.cpl&#xff0c;后面…

js 数据组合,一级结构组合成父子嵌套数组结构

1.方法 buildDeptTree(deptData) { //构建树状部门// 创建一个 map 来存储 deptId 和对应的部门对象const deptMap new Map();// 初始化每个部门对象的 children 属性为空数组deptData.forEach(dept > {dept.children [];deptMap.set(dept.deptId, dept);});// 构建树形结…

Python GUI 开发 | PySide6 PyQt6 学习手册

本文是个 Python GUI 开发的目录&#xff0c;方便读者系统性学习的&#xff0c;笔者后续会满满填充此目录中的内容&#xff0c;感兴趣的小伙伴可以关注一手。&#xff08;主要是偏向 PySide6 方向的&#xff09; 0x01&#xff1a;PySide6 & PyQt6 基础入门 0x0101&#xff…

扣子平台音频功能:让声音也能“智能”起来

在数字化时代&#xff0c;音频内容的重要性不言而喻。无论是在线课程、有声读物&#xff0c;还是各种多媒体应用&#xff0c;音频都是传递信息、增强体验的关键元素。扣子平台的音频功能&#xff0c;为开发者和内容创作者提供了一个强大而灵活的工具&#xff0c;让音频的使用和…

mongoDB常见指令

即使我们自己开发用不到mongoDB&#xff0c;但是接手别人项目的时候&#xff0c;别人如果用了&#xff0c;我们也要会简单调试一下 虽然mongoDB用的不是sql语句&#xff0c;但语句的逻辑都是相似的&#xff0c;比如查看数据库、数据表&#xff0c;增删改查这些 我们下面以doc…

实验二 数据库的附加/分离、导入/导出与备份/还原

实验二 数据库的附加/分离、导入/导出与备份/还原 一、实验目的 1、理解备份的基本概念&#xff0c;掌握各种备份数据库的方法。 2、掌握如何从备份中还原数据库。 3、掌握数据库中各种数据的导入/导出。 4、掌握数据库的附加与分离&#xff0c;理解数据库的附加与分离的作用。…

RubyFPV开源代码之系统简介

RubyFPV开源代码之系统简介 1. 源由2. 工程架构3. 特性介绍&#xff08;软件&#xff09;3.1 特性亮点3.2 数字优势3.3 使用功能 4. DEMO推荐&#xff08;硬件&#xff09;4.1 天空端4.2 地面端4.3 按键硬件Raspberry PiRadxa 3W/E/C 5. 软件设计6. 参考资料 1. 源由 RubyFPV以…

php代码审计2 piwigo CMS in_array()函数漏洞

php代码审计2 piwigo CMS in_array()函数漏洞 一、目的 本次学习目的是了解in_array()函数和对项目piwigo中关于in_array()函数存在漏洞的一个审计并利用漏洞获得管理员帐号。 二、in_array函数学习 in_array() 函数搜索数组中是否存在指定的值。 in_array($search,$array…

PHP校园助手系统小程序

&#x1f511; 校园助手系统 —— 智慧校园生活 &#x1f4f1;一款基于ThinkPHPUniapp框架深度定制的校园助手系统&#xff0c;犹如一把智慧之钥&#xff0c;专为校园团队精心打造&#xff0c;解锁智慧校园生活的无限精彩。它独家适配微信小程序&#xff0c;无需繁琐的下载与安…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.2 ndarray解剖课:多维数组的底层实现

1.2 《ndarray解剖课&#xff1a;多维数组的底层实现》 内容介绍 NumPy 的 ndarray 是其核心数据结构&#xff0c;用于高效处理多维数组。在这篇文章中&#xff0c;我们将深入解析 ndarray 的底层实现&#xff0c;探讨其内存结构、维度、数据类型、步长等关键概念&#xff0c…

计算机网络 (61)移动IP

前言 移动IP&#xff08;Mobile IP&#xff09;是由Internet工程任务小组&#xff08;Internet Engineering Task Force&#xff0c;IETF&#xff09;提出的一个协议&#xff0c;旨在解决移动设备在不同网络间切换时的通信问题&#xff0c;确保移动设备可以在离开原有网络或子网…

css粘性定位超出指定宽度失效问题

展示效果 解决办法&#xff1a;外层容器添加display:grid即可 完整代码 <template><div class"box"><div class"line" v-for"items in 10"><div class"item" v-for"item in 8">drgg</div>&…

10 Hyperledger Fabric 介绍

简介 HypeLedger&#xff08;超级账本&#xff09;是由Linux基金会2015年创建的首个面向企业应用场景的开源分布式账本平台。 HypeLedger Fabric是HypeLedger种的区块链项目之一HypeLedger Fabric引入权限管理在架构设计上支持可插拔、可扩展是首个面向联盟链场景的开源项目 …

分布式光纤应变监测是一种高精度、分布式的监测技术

一、土木工程领域 桥梁结构健康监测 主跨应变监测&#xff1a;在大跨度桥梁的主跨部分&#xff0c;如悬索桥的主缆、斜拉桥的斜拉索和主梁&#xff0c;分布式光纤应变传感器可以沿着这些关键结构部件进行铺设。通过实时监测应变情况&#xff0c;能够精确捕捉到车辆荷载、风荷…

机器学习10-解读CNN代码Pytorch版

机器学习10-解读CNN代码Pytorch版 我个人是Java程序员&#xff0c;关于Python代码的使用过程中的相关代码事项&#xff0c;在此进行记录 文章目录 机器学习10-解读CNN代码Pytorch版1-核心逻辑脉络2-参考网址3-解读CNN代码Pytorch版本1-MNIST数据集读取2-CNN网络的定义1-无注释版…

【C++高并发服务器WebServer】-7:共享内存

本文目录 一、共享内存1.1 shmget函数1.2 shmat1.3 shmdt1.4 shmctl1.5 ftok1.6 共享内存和内存映射的关联1.7 小demo 二、共享内存操作命令 一、共享内存 共享内存允许两个或者多个进程共享物理内存的同一块区域&#xff08;通常被称为段&#xff09;。由于一个共享内存段会称…

稀土抗菌剂:提升产品质量,保障公共健康

随着全球对抗菌技术需求的不断增长&#xff0c;传统的抗菌剂逐渐暴露出其局限性&#xff0c;包括耐药性、环境污染及副作用等问题。在此背景下&#xff0c;稀土抗菌剂作为一种新兴的抗菌材料&#xff0c;凭借其卓越的抗菌性能、环保特性以及应用多样性&#xff0c;正在成为各行…

机器学习11-学习路径推荐

机器学习11-学习路径推荐 本文希望摒除AI学习商业宣传要素&#xff0c;推荐一条极简的AI学习路线&#xff01;推荐内容均为在线免费内容&#xff0c;如果有条件可以咨询专业的培训机构&#xff01; 文章目录 机器学习11-学习路径推荐[toc] 1-AI培训路线第一阶段 Python-人工智能…

《边界感知的分而治之方法:基于扩散模型的无监督阴影去除解决方案》学习笔记

paper&#xff1a;Boundary-Aware Divide and Conquer: A Diffusion-Based Solution for Unsupervised Shadow Removal 目录 摘要 1、介绍 2、相关工作 2.1 阴影去除 2.2 去噪扩散概率模型&#xff08;Denoising Diffusion Probabilistic Models, DDPM&#xff09; 3、方…

java后端之事务管理

Transactional注解&#xff1a;作用于业务层的方法、类、接口上&#xff0c;将当前方法交给spring进行事务管理&#xff0c;执行前开启事务&#xff0c;成功执行则提交事务&#xff0c;执行异常回滚事务 spring事务管理日志&#xff1a; 默认情况下&#xff0c;只有出现Runti…