共识算法Raft

news2024/10/11 22:52:32

引入

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

为了解决这个问题,计算机行内就提出了共识算法,它允许多个分布式节点就某个值或一系列值达成一致性协议,即使在一些节点发生故障、网络分区或其他问题的情况下,共识算法也能保证系统的一致性和数据的可靠性。

常见的共识算法有:Zab、Paxos、Raft。

  • Paxos:一种经典的共识算法,用于解决分布式系统中的一致性问题。业内某知名程序猿曾经提经过说,共识算法本质上只有Paxos一种,其他就是对该共识算法的变种。
  • Raft:一种较新的共识算法,Paxos不易实现,Raft则是对其的简化和改进,旨在易于理解和实现。
  • Zab:ZooKeeper使用的共识算法,基于Paxos算法,并且大部分和Raft相同。主要区别就是对于Leader的任期,Zap叫做epoch,Raft叫做term;还有就是Raft是Leader向Follower发送心跳包,而Zab则刚好相反。
  • Gossip:该算法没有Leader和Follower之分,每个节点都是对等的。当节点中数据改动时,都会告知其他节点。

概述

总的来说,Raft算法是一种共识算法,他的作用就是实现多个节点的数据一致性。

当我们构建一个Raft集群,并对其内部进行一系列的读写操作时,集群内部是如何工作的呢?

1. Raft集群必须存在一个主节点,客户端向集群发起的写操作必须由主节点处理,所以Raft核心算法的第一部分就是选主。假设当前Raft集群没有主节点,那就没法工作,先选出一个主节点之后,再去考虑其他的内容。这部分工作在Raft中称为选主。

2. 有了主节点之后,当客户端发送过来写请求时,主节点就会将其进行包装同步给其他节点。在保证大多数节点都同步了本次操作之后,主节点就会给客户端发起响应了。这部分工作在Raft中称为日志复制。

3. 主节点在Raft算法中承担着非常大的责任,所以只有符合条件的节点才能当选主节点。为了保证集群对外展现的一致性,主节点在处理日志时,也一定要谨慎。这部分工作在Raft中称为安全性。

综上所述,Raft算法将一致性问题分解成了选主、日志复制以及安全性。

基本概念

领导者

领导者(Leader),负责处理客户端的所有修改请求,并将这些请求作为日志复制给跟随者(Follower)。在Raft中,Leader会定期向Follower发送心跳消息,以维持自己的领导地位,防止Follower进入选举过程。

跟随者

跟随者(Follower),接受来自Leader的日志,并将这些日志进行转换,应用为自己的内容。跟随者不会直接处理客户端的修改操作,但是可以处理客户端的读请求。

跟随者

候选者(Candidate),当Follower在一段时间内没有收到Leader发送过来的心跳消息时,Follower就会将自己的身份转变,并开始尝试通过投票成为新的Leader。

在Raft算法中,只能存在一个Leader,并且在集群启动时,所有节点的状态都是跟随者的状态,然后一段时间之内没有收到心跳包时,才会把自己转变成候选者,从而发起选举,使得集群出现了领导者,然后领导者就会一直工作直到他发生异常。

任期

在Raft中,领导者是没有固定任期的,当某一节点成为领导者之后,都是持续工作直到它出现异常为止。假设A点开始选举,然后成为领导者直到它发生异常的这段时间之内,都属于该节点的任期。因此,一段任期的开始时间都是从选举开始,然后到领导者不工作为止。假设在选举时间内没有选举成功,那么也算是一个任期,只不过该任期是以没有领导者而结束的。

任期更像是一个逻辑时钟的作用,有了它,就可以发现哪些节点已经过期,每一个节点都会保持一个任期号,然后在通信的时候带上这个值。

任期号会随着时间单调递增,并且每个节点都会存储一个任期号。节点之间通信时都会携带该任期号,如果一个节点的任期号比其他节点小,那么他就会变更自己的任期号到较大那个值。如果一个候选者或者领导者发现自己的任期号过期了,那么他就会变更成跟随者的状态。如果一个节点收到了一个带着过期任期号的节点,那么他就会忽略这次请求。

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

RequestVote RPCs:请求投票,由候选者选举时发出。

AppendEntries RPCs:由领导者发出,用来做日志复制和发送心跳消息。

选主

1. Raft服务集群启动时,所有的节点都是跟随者的角色,并且每个节点都会有一个超时时间,当等待时间超过过期时间时,跟随者就会进入候选者的角色。

2. 由于启动时,并没有领导者,所以等到等待时间超过超时时间之后,跟随者就会转换成候选者的角色,继而发起投票(此时是因为没有刚启动没有领导者,也有可能是领导者宕机了,或者领导者和跟随者之间发生了网络故障问题等)。

3. 当跟随者成为候选者之后,任期号就会自动增长,同时投给自己一票,紧接着就会发生RPC请求,请其他节点也投自己一票,然后就是等待其他节点的响应。

到了此阶段,就会出现三种情况:

4.1 赢得选举(选举成功的定义是超过半数节点同意自己成为领导者)之后,就会立刻广发消息给其他节点,说自己选举成功了,大家都变成跟随者的状态吧。然后其他节点一看自己的任期号并没有人家的大,那就只能乖乖变成跟随者的状态了。

4.2 还没有等到半数票同意呢,并且等待时间没有超过超时时间,结果此时突然发来个消息说你跟随我吧,现在我是领导者。然后自己一看,人家的任期号比自己大会跟自己相等,那就只能老老实实跟着人家了,自己当个跟随者。

4.3 没有得到半数票同意,又超过了等待时间,那就只能保持候选者状态了,然后增加自己的任期号,重新发起一轮选举,此时就又成为了这三种情况的开头。(出现这种情况的原因可能有所有的节点超时时间相同,那么同一时间过期,导致所有的节点只会投自己一票,从而使得永远没有节点能达不到半数票同意,导致始终没有领导者出现。解决这种现象可以给节点搞一个随机超时时间,这就不会造成同一时间过期的现象了,即使有那也是个例,不影响整体架构)。

投票要求:

一个节点只能投一票。

候选者的任期号必须不能比投票者的小。

日志复制

当有写请求过来之后,Leader通过日志复制管理实现各个节点间的数据同步。

状态机

Raft算法一致性的实现,是基于日志复印状态机的。状态机最大的特征就是,不同节点的状态机若当前状态相同,然后接收了相同的输入,则一定会得到相同结果的输出。

流程

1. 领导者在收到客户端的写请求时,就会把请求的内容和自己的任期号进行封装,然后发送给跟随者,征求大家对此内容的意见,并同时将该请求内容封装为日志。

2. 跟随者收到此次请求之后,首先对比任期号。只要任期号不比自己小,并且两者的日志编号等内容相同,那么就会回复领导者同意,并将此内容封装成日志。

3. 当收到半数同意之后,领导者就会将此日志提交到自己的状态机,状态机会输出一个结果,同时日志状态变成了已提交。

4. 然后领导者还会向跟随者发送请求,告诉跟随者把日志进行提交。

5. 跟随者对日志进行了提交,日志状态也就变成了已提交。

6. 领导者向跟随者发送要求提交的请求时,还会给客户端发出响应。

日志是由任期号、日志的索引和命令组成的,为了保证可用性,各个节点的日志可以不完全相同,但是领导者会持续不断的发送内容给跟随者,以促使各个节点的日志最终达到相同。因此,Raft算法是保持最终一致性。

脑裂

脑裂指的是本来是在一个集群中处理消息的节点,因为某些原因而不能通信,导致两端都开始处理消息,从而使得系统混乱,数据错误的现象。

Redis集群存在脑裂现象,在多机房部署中,由于网络连接问题,很容易生成多个分区,而多分区的形成,很容易产生脑裂,从而导致数据出现问题。

在日常生产环境中,三机房的容灾能力是最强的,所以以三机房为例,来进行分析断网之后,出现的五种情况的后果:

情况一

在这种情况中,B与领导者A之间发生了网络问题,B的超时时间一过,B就会成为候选者,给C一发请求,C一看任期号比自己大,所以自己就会成为B的跟随者,而A与B此时不能进行交互,导致A也是领导者,B也是领导者。当有请求来时,A接受请求,但是最终由于票数没有大于一半,不会响应该请求,不过B能够成功响应。这就导致了读请求来时,A给出的数据可能不是正确数据。

综上所述,当领导者和某一跟随者之间无法通信时,就会出现脑裂现象。

情况二:

当B和C同时与A发生了网络故障时,两个跟随者无论谁先到达超时时间都会决出新的领导者,这就导致了三机房中出现了两位领导者,从而出现了脑裂问题。

情况三:

 

当ABC三者之间都出现了网络故障,此时虽然BC都会去进行选举,但是没有一个能选举成功,所以此时只有A可以提供读服务,BC则不能提供服务。

情况四:

 当出现上述情况时,B会进行选举,但是并不能选举成功,因为它永远得不到半数票的同意,所以并不会出现脑裂现象。并且,B不会对外提供服务,A和C则可以继续正常对外服务。

情况五:

当出现上述情况时,系统仍会正常工作,不会出现任何问题。

综上所述,在三个机房可能出现的五种情况中,也不是都会出现脑裂现象。并且我们发现,出现脑裂现象之后,从前的领导者都是不能响应写请求,因此我们可以在写项目中,加上一个判断就是当领导者长期不能应对写请求时,就自动下线或者进行其他处理。 

领导者宕机处理

请求到达领导者之前挂了:此时请求并没有到达Raft集群,所以Raft集群中并没有任何一个节点会对此请求有任何的处理。当新领导者上线以后,也不会认为有任何的不妥。此时如果客户端有重试机制的话,就会重新发送请求过来,Raft集群进行正常处理。

请求到达领导者,但是领导者还没有发送数据时挂了:新领导者选举出来之后,由于新领导者并没有该请求的任何消息,所以并不会进行任何响应。并且当新领导者同步各个节点时,由于之前的旧领导者有这条消息,旧领导者还会将此消息丢弃出来。

请求向跟随者发送部分之后挂掉了:此时选举出领导者之后,会有两种情况出现。第一种是新领导者有该消息的存在,所以会进行同步,最后返回响应;第二种就是恰好不存在该消息,那么就不会进行同步,也不会发起响应。

领导者向跟随者发送提交后挂掉了:此时已经成功发送了提交,并且提交的同时还会向客户端响应,那已经成功了,此时新领导者上来也不会处理啥,因为已经成功了。

在日志复制中,对一些较为详细的内容并没有介绍到。其实,向跟随者发送日志条目的啥时候,有很多的内容,因为要保证节点的数据一致性,所以就要判断以前的日志条目是否相同。但是由于并不是详细了解其工作原理,所以只进行了一个大致介绍,同学们也只需要大致了解就能应对面试官的大多数问题了。

概述来说,由于各个节点之间数据是不可能每次都能同步成功,并且由于宕机等问题,数据可能确实很多。所以日志复制,基本上是上述的简单流程,不过假设某一结点数据或缺许多时,领导者也会慢慢找到或缺的数据,然后给他全部补上,保持一个数据的最终一致性。

总的来说,Raft共识算法就是用来保证集群中数据一致性的。为了保证其数据一致性,内部大概分成了选主、日志复制、安全性等内容。 

应用场景

1. 在Redis中,使用哨兵机制时,当Redis主节点发生问题之后,哨兵节点就会进行选主,然后对主从集群进行操作,选主的过程就是使用的Raft算法。

2. 在RabbitMQ构建集群中,仲裁队列内部使用的也是Raft算法。本身创建的是普通队列,这就导致单点问题。不过创建仲裁队列之后,利用Raft算法就可以将队列和消息在不同的节点都进行存储。假设创建队列的节点出现故障之后,其他节点依然能够针对该队列进行工作。

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

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

相关文章

git gui基本使用

一、图形化界面 二、创建新项目 创建文件,加入暂存区,提交到版本库 三、创建分支 四、合并分支 1.切换至master 五、更新分支 六、解决冲突 修改冲突,加入暂存区,提交到版本库 七、远程创建库 Gitee - 基于 Git 的代码托管和研…

低功耗

低功耗 目录 低功耗 STM32中的电源系统 STM32 中的低功耗 相关代码 -- 首先我们先看我们做的项目如何降低功耗 -- 对于设备,功耗怎么降低?把设备上所有的电子模块,都进入低功耗模式。 对于空气质量检测仪,如何降低功耗&…

修改armbian DNS服务器地址(永久修改DNS配置)

linux dns服务器地址的配置文件在/etc/resolv.conf 但系统可能设置的是默认值,也就是192.168.1.1。导致系统无法正常解析域名,进而导致有一些接口无法调用或下载失败。 最直接的思路就是修改/etc/resolv.conf,将其中的nameserver修改为正确的…

必看系列:面试官通过一个问题考查了网络编程所有知识点!

一、写在开头 本文的主题是和大家一起探讨学习:“在浏览器中输入URL开始后,计算机所做的几件事”,这个问题是好几年前自己面试的时候,面试官考问过的,当时准备十分不充分,回答的一塌糊涂,今天拿出来再整理学习一遍,一同进步! 其实这个问题本身倒是不难,但它巧妙的是…

节假日提醒,节假日任务,节假日判断如何做?这篇文章教会你!

你是否有这样的需求,有一个任务需要在大家都休息的时候处理,你肯定会想到周六周日了,那不好意思,遇到调休怎么办呢?遇到国假怎么办呢?我这里所说的节假日和工作日不仅仅指正常的周一至周日,还包…

浙江省发规院产业发展研究所调研组莅临迪捷软件考察调研

2024年10月10日下午,浙江省发展与规划院产业发展研究所调研组一行莅临迪捷软件考察调研,绍兴市府办、区发改、区经信、迪荡街道等相关领导陪同。 调研组一行参观了迪捷软件的展厅与办公区,深入了解了迪捷软件的公司发展历程、运营状况、产品…

Python 如何使用 Bert 进行中文情感分析

前言 在自然语言处理(NLP)领域,情感分析是一个非常常见且重要的应用。情感分析通常用于识别文本中的情感,例如判断一条微博或评论是正面、负面还是中性。在过去的几年中,随着深度学习的发展,BERT&#xff…

MySQL表的基本操作和数据类型

MySQL表的基本操作和数据类型 表的操作创建表修改表删除表 数据类型数值类型整型浮点型 文本、二进制类型日期时间类型ENUM类型和SET类型 表的操作 创建表 语法: CREATE TABLE table_name(field1 datatype,field2 datatype,field3 datatype )character set 字符集…

Python的matplotlib可视化工具基本操作(数据分析生成图表)

一、安装导入 1、使用包管理器安装matplotlib pip3 install matplotlib 2、导入plt工具 import matplotlib.pyplot as plt 二、基本函数 1、创建图表 使用pyplot工具打点调用创建图表函数 例如创建直方图: import matplotlib.pyplot as plt import pandas…

【unity框架开发9】序列化字典,场景,vector,color,Quaternion

文章目录 前言一、可序列化字典类普通字典简单的使用可序列化字典简单的使用 二、序列化场景三、序列化vector四、序列化color五、序列化旋转Quaternion完结 前言 自定义序列化的主要原因: 可读性:使数据结构更清晰,便于理解和维护。优化 I…

Android Framework默认授予app通知使用权限

安卓通知使用权限 在安卓系统中,应用程序需要获取通知使用权限才能向用户发送通知。以下是关于安卓通知使用权限的一些信息: 权限获取方式 当用户安装应用时,系统可能会在安装过程中提示用户授予应用通知权限。用户可以选择允许或拒绝。 应…

记录一些yolo-world训练数据集的报错

参考的这个文章 https://blog.csdn.net/ITdaka/article/details/138863017?spm1001.2014.3001.5501 openai快捷下载:https://download.csdn.net/download/qq_43767886/89876720 然后我打算训练coco数据集,遇到了以下的问题 问题一 原因:…

智慧农田新篇章:高标准农田灌区信息化的创新实践

在新时代的农业发展蓝图中,智慧农田已成为推动农业现代化、实现可持续发展目标的关键一环。高标准农田灌区信息化作为智慧农业的重要组成部分,正引领着一场深刻的农业技术革命,它不仅关乎粮食安全与资源高效利用,还深刻影响着农村…

writehelpAI论文写作,专业毕业论文救星

撰写专业毕业论文是每位学生学术旅程中的一个重要里程碑,它不仅检验了你对专业知识的掌握程度,还考验着研究能力、批判性思维以及书面表达技巧。在这个过程中,writehelpAI这样的智能写作助手可以成为你的得力伙伴,帮助解决从选题到…

功率检测和语音功能

INA226 INA226 High-Side or Low-Side Measurement, Bi-Directional Current and Power Monitor with I2C Compatible Interface datasheet (Rev. A) INA226功率监测模块原理 7.5 编程 INA226 器件的一个重要方面是它不一定测量电流或功率。该器件可测量施加在 IN 和 IN- 输入…

数据结构重点学习笔记教程——入门必看 数据结构心得

数据结构教程知识点 章节目录 一、数据结构概述二、线性表三、栈与队列四、数组与字符串五、树与二叉树六、图七、排序算法八、查找算法九、哈希表与散列法十、高级数据结构 总结简介 本数据结构教程知识点涵盖了从数据结构概述到高级数据结构的全方位内容,旨在帮…

河南省学籍管理员在校拍照采集学生证件照流程介绍

校园证件照采集是校园管理中一个重要的环节,它涉及为学生、教职工等校园成员拍摄并处理符合特定要求的证件照片。以下是针对河南省中小学生学籍照片集中拍摄采集的步骤指南,用于指导学籍管理员开展相关工作。 一、学籍照片采集的前期准备 (1…

Java读取Excel文件_详细可执行_低内存占用

EasyExcel介绍:高效内存友好Java Excel处理工具,轻松应对大文件 EasyExcel是一个基于Java的、快速且简洁的Excel处理工具,专为解决大文件内存溢出问题设计。与传统的Excel处理框架如Apache POI和jxl相比,它显著降低了内存消耗。例…

linuxC高级_day5(完结)

目录 指针函数 1.概念 2.定义格式 3.函数内开辟空间 函数指针 1.概念 2.定义格式 2.1 格式 3.函数指针数组 3.1 概念 3.2 格式 3.3 赋值 条件编译 1.根据宏是否定义 根据宏值 3.防止头文件重复包含 指针函数 1.概念 本质是函数,函数返回值是指针。类…

C++系统教程004-数据类型(03)

一 .变量 变量是指在程序运行期间其值可以发生改变的量。每个变量都必须有一个名称作为唯一的标识,且具有一个特定的数据类型。变量使用之前,一定要先进行声明或定义。 1.变量的声明和定义 C中,变量声明是指为变量提供一个名称&#xff0c…