首页 > 其他分享 >RabbitMQ集群 - 仲裁队列、Raft协议(最详细的选举流程)

RabbitMQ集群 - 仲裁队列、Raft协议(最详细的选举流程)

时间:2024-08-18 16:58:42浏览次数:11  
标签:选举 队列 任期 RabbitMQ Leader Raft 节点

文章目录

仲裁队列


概述

1)RabbitMQ 普通队列在一个节点宕机之后,其他节点无法读写宕机节点的队列,为了解决这个问题,引入了仲裁队列.

2)仲裁队列通过 Raft 协议,实现了不同节点间队列消息数据的复制,使得在 创建这个队列的节点 宕机时,其他节点仍然可以使用该队列进行服务.

Ps:仲裁队列时 RabbitMQ3.8 版本的重要改动,是 镜像队列 的替代方案(设计上有缺陷). 镜像队列已被弃用,并计划在将来的版本中移除.

Raft 协议

概述

在分布式系统中,为了解决单点问题,通常会使用副本(从节点)来进行容错,但这又引入了另外一个问题——“如何保证副本之间的一致性?”.

共识算法就是来解决这个问题的,它可以使得一些节点发生故障、网络分区或其他问题情况下,也能保证系统的一致性和数据可靠性,而 Raft 就是 共识算法 中的一种.

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

Ps:除了 Raft 还有很多其他的共识算法,例如 Paxos、Zab、Gossip

基本概念

1)节点角色
在 Raft 算法中,每个节点都有以下 3 个角色之一:

  • Leader(领导者):负责处理所有客户端的请求,并将这些请求作为日志,发送给所有的 Follower. Leader 会定期向所有 Follower 发送心跳消息,告诉他们 “我是领导,我还活着”,防止 Follower 进入选举流程.
  • Follower(跟随者):跟随者 不直接处理客户端请求,而是接受 Leader 发送的日志,并使用这些信息.
  • Candidate(候选者):当 跟随者 在一段时间内没有收到 Leader 的心跳消息,就会变成 Candidate,并开始进入选举流程.’

大致流程:所有节点在刚启动时都是 follow 状态,在一段时间内如果没有收到来自 leader 的心跳,就会从 follower 切换到 candidate,发起选举. 如果收到多个投票(> n/2,包括自己的一票),则切换到 leader 状态,然后一直工作到它发生异常为止.

2)任期(term)
从一次选举开始,到一个 leander 最后宕机,就是一次任期. 如果一次选举没有选出 leader,这个任期会以没有 leader 而结束.

每个节点会存储当前任期号(current term number),并且会随着每次选举成功后单调递增.
节点之间通信的时候会交换任期号:

  • 如果一个 跟随者 节点的 任期号 小于其他节点,他就会将自己的任期号更新为较大的那个值.
  • 如果一个 候选者 或 领导者 节点的 任期号过期了(请求当leader票 或 发送心跳包 时顺带判断),他就会立即回到 follower 状态.
  • 如果一个节点收到了带着过期的任期号的请求,那么他会拒绝这次请求.

例如新的主节点的任期号为2,而 旧的主节点恢复了连接(任期号为1),给其他节点发送信号,其他节点一看,比我还小,就不听他的,并且告诉旧主机点,现在已经是 任期号为2 的年代了,此时旧的主节点就会把修改自己的任期号为2,并且将自己修改为 Follower 的角色.

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

  • RequestVote RPCs:请求投票,由 候选者 在选举过程中发出.
  • AppendEntries RPCs:追加条目,由 leader 发出,用来做日志复制和提供心跳机制.

选举流程(重点)

选主(Leader election)就是在集群中选择出一个主节点来负责特定工作(类似于公司的领导).

Note:正常情况下,集群中只有一个 Leader,剩下的节点都是 follower.

1)服务器刚启动的时候,所有节点都是 follow 状态,如果 follower 在 选举超时时间(election timeout) 内没有收到来自 leader 的心跳(可能:没有选出 leader、leader 挂了、leader 与 follower之间网络故障),则会主从发起选举. 步骤如下:

  • 第一个超时的节点,自增当前任期号,然后切换为 候选人 状态,并先给自己投一票.
  • 以并行的方式给集群中其他节点发送一个 RequestVote RPCs. (想要得到其他人的投票)

在这个过程中,可能会出现三种结果(后面会细致说明这三种情况):

  1. 赢得选举,称为 Leader(包括自己的一票).
  2. 其他节点赢得选举,它自行切换到 follower.
  3. 在 选举超时时间 内没有凑够 > n/2 的票数,就会保持 候选人状态,重新发出选举.
    在这里插入图片描述
    其他节点收到票后,判断如果符合 任期要求,就会会按照先来先服务原则(first-come-first-served)值投给一个 候选人.
    投票之后,会将自己的 任期 和 候选人 一致.
    在这里插入图片描述

2)第一种情况:赢得选举后,新的 leader 会立即给所有节点发消息,避免其余节点触发新的选举.
在这里插入图片描述
3)第二种情况:其他节点赢得选举成为 Leader,并且收到了 Leader 的心跳包,判定任期符合要求,然后就会将自己转为 follower.
在这里插入图片描述
在这里插入图片描述
4)第三种情况:没有任何一个节点获得 半数投票. 例如所有 follower 同时变成 candidate,然后他们都给先给自己投一票,这样就没有 candidate 能超过半数投票了.

在这里插入图片描述

那岂不是形成了一个闭环(永远没有节点能超过半数投票)?

为了解决这个问题,Raft 采用随机选举超时时间. 选举时间会从一个 固定的区间(比如 150-300ms)种随机选择. 这样就可以确保大部分情况下不会发生所有人同时再次选举,发起拉票的情况.
在这里插入图片描述
在这里插入图片描述

Ps:Raft 在线演示地址 https://raft.github.io/

消息复制

每个仲裁队列都有多个副本,包含 一个主 和 多个从副本,每个 副本都在不同的 RabbitMQ 节点上.

客户端(生产者 和 消费者)只会和 主节点 进行交互,主节点 再将这些命令复制到 从节点. 当 主节点 下线,其中一个 从节点 就会被选举成为 主节点,继续提供服务.

当之前 挂掉的主节点 重新上线后,发现自己的任期号 小于 当前 Leader 的任期号,就会将自己变为 Follower.

仲裁队列的使用

MQ 管理平台

在这里插入图片描述

Spring AMQP

1)配置

spring:
  application:
    name: rabbitmq
  rabbitmq:
    host: env-base
    port: 5672
    username: root
    password: 1111

2)Bean

import com.cyk.rabbitmq.constants.MQConst
import org.springframework.amqp.core.Queue
import org.springframework.amqp.core.QueueBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class QuorumConfig {

    @Bean
    fun quorumQueue(): Queue = QueueBuilder
        .durable(MQConst.QUORUM_QUEUE)
        .quorum()
        .build()

}

3)生产者接口

@RestController
@RequestMapping("/mq")
class MQApi(
    private val rabbitTemplate: RabbitTemplate
) {

    @GetMapping
    fun quorum(): String {
        rabbitTemplate.convertAndSend("", MQConst.QUORUM_QUEUE, "quorum msg 1")
        return "ok"
    }

}

4)触发端点,效果如下:
在这里插入图片描述
可以看到 仲裁队列 Node 这里 rabbit@mq1 +2 有一个 +2 的字样,代表整个队列有 2 个镜像节点.
进去可以看到 Leader 和 其他从节点是谁.
在这里插入图片描述
此时,将创建 仲裁队列 的节点下线(docker stop mq1),观察其他节点仲裁队列的信息,发现依旧可以提供服务.
在这里插入图片描述
在这里插入图片描述

标签:选举,队列,任期,RabbitMQ,Leader,Raft,节点
From: https://blog.csdn.net/CYK_byte/article/details/141285666

相关文章

  • RabbitMQ-消息队列之topic使用
    1、安装rabbitmq怎么安装rabbitmq请查看之前课程,如果已经安装,请略过此步。2、创建vendor文件夹或是直接采用PHP框架mkdirvendor3、进入文件cdvendor4、安装php扩展composerrequirephp-amqplib/php-amqplib5、进入上级创建topic文件夹cd../mkdirtopic6、进入to......
  • 链式队列的实现方式
    C语言实现链队列LinkQueue.h////CreatedbyAdministratoron2024/8/17.//#ifndefLINKQUEUE_H#defineLINKQUEUE_H#include<stdbool.h>/**定义队列元素结构体*/typedefintDataType;typedefstructLinkQueueNode{DataTypedata;//数据域structLi......
  • RabbitMQ实现消息可靠性的三种方法(发送者可靠性,MQ可靠性,消费者可靠性)
    1.发送者可靠性1.1发送者重连RabbitMQ的发送者重连机制是一种应对网络不稳定或连接中断情况的策略,它能够自动尝试重新建立与RabbitMQ服务器的连接,以确保消息能够成功发送。发送者重连通常涉及到一些配置参数,如连接超时时间、重试间隔、最大重试次数等。例如,在Spring框架的......
  • [Redis]延迟消息队列
    延迟消息队列redis数据结构,用什么结构实现延迟消息队列延迟消息队列是一种消息队列系统,它允许消息的发布者在消息发送时指定消息的投递时间,使消息在未来的某个预定时间点被消费者接收。这种机制对于需要在稍后执行的任务或具有特定延迟需求的应用非常有用。对于实现延迟消息队......
  • RabbitMQ面试题
    一、RabbitMQ如何保证消息的可靠性RabbiMQ如果想要保证消息的可靠性有几种方式可以实现:1、消费端消息可靠性保证:1).消息确认在消费端可以设置手动ACK模式,为确保消息可靠性,手动确认消息是否被正常处理,若存在异常或者未运行,则消息超时后不会被删除,会被重新投递2).死信队列......
  • RabbitMQ-记录一个问题及解决
    我在配置文件中写入了rabbitmq:host:127.0.0.1port:5672username:guestpassport:guestvirtualhost:/switchFlag:truepool_size:10然后希望实现一个监听器,所以加上了注解形式@RabbitListener(queues=CommonConstants.QUERE_NAME_NOTIFY),由于我工作......
  • RabbitMQ的介绍
    一、什么是MQMQ(messagequeue),从字面意思上看就个FIFO先入先出的队列,只不过队列中存放的内容是message而已,它是一种具有接收数据、存储数据、发送数据等功能的技术服务。消息指的是两个应用间传递的数据。数据的类型有很多种形式,可能只包含文本字符串,也可能包含嵌入对象......
  • DelayQueue 延迟队列使用
    一、DelayQueue是什么DelayQueue是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期时间最长。注意:不能将null元素放置到这种队列中。二、DelayQueue能做什么1.淘宝订单业务:下......
  • 第七节:消息队列推拉模式选择、kafak如何提高吞吐量、超时关单和支付成功同时出现咋办
    一.        二.        三.         !作       者:Yaopengfei(姚鹏飞)博客地址:http://www.cnblogs.com/yaopengfei/声     明1:如有错误,欢迎讨论,请勿谩骂^_^。声     明2:原创博客请在转载......
  • BackgroundWorker和BlockingCollection配合实现有消息才发送的队列
    privateBackgroundWorkerm_MessageConsumer=newBackgroundWorker();privateBlockingCollection<string>m_BlockingQueue=newBlockingCollection<string>();构造函数{m_MessageConsumer.DoWork+=M_MessageConsumer_DoWork;m_MessageConsumer.Work......