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

RabbitMQ ⑥-集群 || Raft || 仲裁队列

在这里插入图片描述

搭建 RabbitMQ 集群

多机多节点

准备三台服务器,确保这三台服务器处于同一个局域网内。

安装 RabbitMQ,此步骤省略

配置 host 文件

vim /etc/hosts
# rabbitmq
10.0.0.232 iZ2vc7a1n9gvhFp589oav8Z
10.0.0.233 iZ2vc7a1n9gvhFp589oav6Z
10.0.0.234 iZ2vc7a1n9gvhFp589oav7Z

具体的主机IP和主机名可以通过 iFconFigmore /etc/hostname 命令查看。

配置 Erlang Cookie

  • RabbitMQ 节点和 CLI 工具使用 Cookie 来进行身份验证,确认它们之间是否被允许相互通信。为了使两个节点可以通信,它们必须具有相同的共享密钥,称为 Erlang Cookie。
  • 停止所有节点服务:systemctl stop rabbitmq-server
  • 配置 Erlang Cookie:
#拷贝 node3节点的文件到 node1
scp /var/lib/rabbitmq/.erlang.cookie
root@iZ2vc7a1n9gvhFp589oav8Z:/var/lib/rabbitmq/#拷贝 node3节点的文件到 node2
scp /var/lib/rabbitmq/.erlang.cookie
root@iZ2vc7a1n9gvhFp589oav6Z:/var/lib/rabbitmq/
  • 以后端的方式启动三台节点:rabbitmq-server -detached

构建集群

为了将集群中的三个节点连接起来,需要告诉另外两个节点加入另一个节点,比如 node1 和 node2 加入 node3。

#1. 关闭 RabbitMQ 服务
rabbitmqctl stop_app#2. 重置当前节点
rabbitmqctl reset#3.加入节点 后面跟的是 node3节点
rabbitmqctl join_cluster rabbit@iZ2vc7a1n9gvhFp589oav7Z#4. 启动服务
rabbitmqctl start_app

验证集群状态

rabbitmqctl cluster_status

也可以在管理平台查看到
在这里插入图片描述
如果发现某一个节点显示 Node statistics not available 字样,说明该节点的 Web 管理插件未启用。

rabbitmq-plugins enable rabbitmq_management

单机多节点

多机多节点对 “大米” 的要求较高,不适合学习。所以,我们选择单机多节点的方式来搭建 RabbitMQ 集群。

准备一台服务器

安装 RabbitMQ,此步骤省略

额外启动两个节点

  • 第二个节点:Node name:rabbit2AMQP 协议端口号:5673;Web 管理端口号:15673
  • 第三个节点:Node name:rabbit3AMQP 协议端口号:5674Web 管理端口号:15674
RABBITMQ_NODE_PORT=5673 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management
listener [{port,15673}]" RABBITMQ_NODENAME=rabbit2 rabbitmq-server -detachedRABBITMQ_NODE_PORT=5674 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management
listener [{port,15674}]" RABBITMQ_NODENAME=rabbit3 rabbitmq-server -detached

验证是否启动成功

分别输入 ip:15673 和 ip:15674 访问 RabbitMQ 管理平台,查看是否正常访问。

构建集群

停止服务并重置

rabbitmqctl -n rabbit2 stop_app
rabbitmqctl -n rabbit2 resetrabbitmqctl -n rabbit3 stop_app
rabbitmqctl -n rabbit3 reset

将 rabbit2 和 rabbit3 节点加入到 rabbit1 节点,可以通过 rabbitmqctl status 查询 rabbit1 的 Node 名称。

rabbitmqctl -n rabbit2 join_cluster rabbit@hcss-ecs-2618rabbitmqctl -n rabbit3 join_cluster rabbit@hcss-ecs-2618

启动服务

rabbitmqctl -n rabbit2 start_apprabbitmqctl -n rabbit3 start_app

查看集群状态

rabbitmqctl cluster_status -n rabbit

或者通过 Web 管理平台查看

宕机演示

安装之后,是有问题的,也就是数据不同步。

我们在任意一个节点创建队列,并且发送发送消息到该队列,可以看到其他队列也是有该节点和消息的。

此时,我们将之前创建该队列的节点停止,也就是模拟宕机。关闭后发现,其他节点的该队列也停止了,尽管重新启动后,该队列依然存在,但是消息却消失了。

仲裁队列(Quorum Queues)

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

仲裁队列的特点:

  • 队列复制的能力:将该节点创建的队列复制到其他节点,尽管该节点宕机了,其他节点依然有该队列的存在和存储的消息。
  • 保障数据的高可用和安全性。

官方文档:Quorum Queues

仲裁队列是 RabbitMQ 3.8 版本最重要的改动。他是镜像队列的替代方案。在这之前,镜像队列是实现数据高可用的唯一手段,但是它存在一些问题,所以镜像队列被废弃了。

Raft

这是官方论文的摘要:

Raft is a consensus algorithm for managing a replicated
log. It produces a result equivalent to (multi-)Paxos, and
it is as efficient as Paxos, but its structure is different
from Paxos; this makes Raft more understandable than
Paxos and also provides a better foundation for build-
ing practical systems. In order to enhance understandabil-
ity, Raft separates the key elements of consensus, such as
leader election, log replication, and safety, and it enforces
a stronger degree of coherency to reduce the number of
states that must be considered. Results from a user study
demonstrate that Raft is easier for students to learn than
Paxos. Raft also includes a new mechanism for changing
the cluster membership, which uses overlapping majori-
ties to guarantee safety.
Raft 是一个用于管理复制日志的共识算法。它产生的结果等价于(多)Paxos,并且与 Paxos 一样高效,但是它的结构与 Paxos 不同,这使得 Raft 更容易理解,也为构建实用的系统提供了更好的基础。为了增强理解性,Raft 将共识的关键元素分离开来,如领导人选举、日志复制和安全性,并强化了强一致性,以减少必须考虑的状态数量。用户研究的结果表明,Raft 对学生来说更易于学习,而 Paxos 则更难。Raft 还包括了一个用于改变集群成员资格的新机制,该机制使用重叠的多数来保证安全性。

有兴趣的可以直接去看论文:Raft论文

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

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

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

常见的共识性算法有 Paxos、Zab、Raft、Gossip 等。

Raft 使用 Quorum 机制来实现共识和容错,我们对 Raft 集群的操作必须得到大多数(> N/2)节点的同意才能提交。

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

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

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

Raft 算法将一致性问题分解为三个子问题:Leader 选举、日志复制和安全性。

选主(Leader Election)

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

节点角色

在 Raft 中,所有节点都处于以下三个角色之一:

  • Leader(领导者):负责处理所有客户请求,并将这些请求作为日志项复制到所有 FollowerLeader 定期向所有 Follower 发送心跳消息,以维持其领导者地位,防止 其他 Follower 进入选举过程。
  • Follower(跟随者):收来自 Leader 的日志条目,并在本地应用这些条目。跟随者不直接处理客户请求。
  • Candidate(候选者):当跟随者在一段时间内没有收到来自 Leader 的心跳消息时,它会变得不确定 Leader 是否仍然可用。在这种情况下,跟随者会转变角色成为 Candidate,并开始尝试通过投票过程成为新的 Leader

正常情况下,集群只有一个 Leader,其他节点都是 Follower
在这里插入图片描述
可以看出所有节点在启动时,都是 Follower 状态,在一段时间内如果没有收到来自 Leader 的心跳,从 Follower 切换到 Candidate,发起选举。如果收到多数派(Majority)的投票(含自己的一票),则切换到 Leader 状态。Leader 一般会一直工作直到它发生异常为止。

任期

Raft 将时间划分成任意长度的任期(Term)。每一段任期从一次选举开始,在这个时候会有一个或者多个 Candidate 尝试去成为 Leader。在成功完成一次 Leader election 之后,一个 Leader 就会一直节管理集群直到任期结束。在某些情况下,一次选举无法选出 Leader,这个时候这个任期会以没有 Leader 而结束。同时一个新的任期(包含一次新的选举)会很快重新开始。
在这里插入图片描述
Term 更像一个逻辑时钟(Logic Clock)的作用,有了它,就可以发现哪些节点的状态已经过期。每一个节点都保存一个 Current Term,在通信时带上这个 Term 的值。

每一个节点都存储着一个当前任期号(Current Term Number)。该任期号会随着时间单调递增。节点之间通信的时候会交换当前任期号,如果一个节点的当前任期号比其他节点小,那么它就将自己的任期号更新为较大的那个值。如果一个 Candidate 或者 Leader 发现自己的任期号过期了,它就会回到 Follower 状态。如果一个节点接收了一个带着过期的任期号的请求,那么它会拒绝这次请求。

假设当前的 Leader 节点宕机了,那么集群会进入选举过程,选出一个新的 Leader。但是宕机的 Leader 节点并不知道自己已经不是 Leader,所以在恢复时,该节点还一直认为自己是 Leader,此时存在两个 Leader,就会发生冲突。

由于 Term 的存在,并不存在该问题,这是因为重新进入选举后,Term 会比之间要大,当先前的 Leader 宕机又回归后,继续发送心跳包表示自己是 Leader,此时其他 Follower 发现该心跳包的 Term 号比自己小,就会拒绝该心跳包,先前的 Leader 知道后就会变回为 Follower

Raft 算法中服务器节点之间采 RPC 进行通信,主要有两类 RPC 请求:

  • RequestVoteRPCs:请求投票,由 Candidate 在选举过程中发出
  • AppendEntriesRPCs:追加条目,由 Leader 发出,用来做日志复制和提供心跳机制。

选举过程

Raft 采用一种心跳机制来触发 Leader 选举,当服务器启动的时候,都是Follower 状态。如果 Follower 在 Election timeout 内没有收到来自 Leader 的心跳 (可能没有选出 Leader,也可能 Leader 挂了,或者 LeaderFollower 之间网络故障),则会主动发起选举。

步骤如下:

  1. 率先超时的节点,自增当前任期号然后切换为 Candidate 状态,并为自己先投一票
  2. 以并行的方式发送一个 RequestVoteRPCs 给集群中的其他服务器节点(企图获得它们的投票)
  3. 等待其他节点的回复
    在这里插入图片描述
    在这个过程中,可能出现三种结果:
  • 赢得选举,成为 Leader
  • 其他节点赢得了选举,它自行切换到 Follower 状态
  • 一段时间内没有收到 Majority 的投票,保持 Candidate 状态,重新发出选举。

赢得选举后,Leader 会立即给所有其他节点发送消息,告知自己是 Leader,避免又开始新一轮的选举。
在这里插入图片描述
如果在同一时刻有两个或两个以上的节点都超时了,也就是它们可能会同时发起选举。比如有 A、B、C 三个节点,A 和 B 同时发起选举,而 A 的选举消息率先到达 C,C 给 A 投了一票,那么之后就不能投票了,此时 B 的选举消息发来后,C 会发送一个拒绝消息表示我已经投给其他节点了。A 胜出后,会给所有结点发消息告知自己是 Leader,B 发现 A 的 Term 不必自己低,就说明其他节点赢得了选举,B 就会切换到 Follower 状态。
在这里插入图片描述
如果任何节点获得 Majority 投票,比如所有的 Follower 同时变成 Candidate,它们一开始会立刻投票给自己,导致就没有一个 Candidate 可能超过半数投票。当这种情况发生时,每个 Candidate 都会进行一次超时响应,然后通过自增 Term 来开启新一轮的选举,如果没有额外的应对措施,这种无结果的投票可能会无限重复下去。
在这里插入图片描述
为了解决上述问题,Raft 采用随机选举超时时间(Randomized election timeouts) 来确保很少产生无结果的投票,并且就算发生了也能很快地解决。为了防止选票一开始就被瓜分,选举超时时间是从一个固定的区间(比如,150-300ms)中随机选择。这样可以把节点分散开来以确保在大多数情况下会只有一个节点率先结束超时,那么这个时候,它就可以赢得选举并在其他节点结束超时之前发送心跳。

Raft 算法动画演示在线地址1
Raft 算法动画演示在线地址2

日志复制(Log Replication)

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

客户端(生产者和消费者)只会与主副本进行交互,主副本再将这些命令复制到从副本。当主副本所在的节点下线,其中一个从副本会被选举成为主副本,继续提供服务。
在这里插入图片描述
消息复制和主副本选举的操作,需要超过半数的副本同意。当生产者发送一条消息,需要超过半数的队列副本都将消息写入磁盘以后才会向生产者进行确认,这意味着少部分比较慢的副本不会影响整个队列的性能的。

使用仲裁队列

@Bean("quorumQueue")
public Queue quorumQueue() {return QueueBuilder.durable("quorum_queue").quorum().build();
}
Map<String, Object> args = Map.of("x-queue-type", "quorum");
channel.queueDeclare("quorum_queue", true, false, false, args);

HAProxy

我们可以在客户端引入 HAProxy 负载均衡,确保每个节点分摊合理的流量请求;以及确保一个节点宕机时不会影响整个服务。

相关文章:

  • 数据库设计文档撰写攻略
  • vscode使用ssh链接服务器
  • Postgresql 数据库实例管理命令
  • mybatis-plus与jsqlparser共用时报sql解析错误
  • 第十天 高精地图与定位(SLAM、RTK技术) 多传感器融合(Kalman滤波、深度学习)
  • 射频芯片学习
  • 学习黑客TTryHackMe — Tcpdump基础 | 网络安全入门(THM)
  • 【漫话机器学习系列】274.基尼指数(Gini Index)
  • Oracle常用函数
  • LVS 负载均衡集群应用实战
  • 数据库系统概论(九)SQL连接查询语言超详细讲解(附带例题,表格详细讲解对比带你一步步掌握)
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(28):ばかり
  • SQL 的 DECODE 函数
  • MacOS Docker 启动 RustDesk Server OSS
  • 多版本Node.js共存管理工具NVM详细使用教程
  • postgresql 常用参数配置
  • 第七部分:第二节 - 在 Node.js 中连接和操作 MySQL:厨房与仓库的沟通渠道
  • Postgresql 数据库体系架构
  • 从逆流监测到智慧用电:ADL200N-CT系列单相导轨表赋能家庭绿色能源
  • 储能电站:风光储一体化能源中心数字孪生
  • 婚纱网站策划书模板下载/短链接在线生成
  • 做五金有哪些网站推广/手机网站免费客服系统
  • ps怎么做网站模板/网站浏览器
  • 杭州做外贸网站/重庆疫情最新消息
  • 做seo网站公司哪家好/网络营销的六个特点
  • 免费做简历的软件网站/线下营销推广方式有哪些