Raft分布式一致性算法

news2024/11/18 6:35:05

拜占庭将军

假设多位拜占庭将军中没有叛军,信使的信息可靠但有可能被暗杀的情况下,将军们如何达成是否要进攻的一致性决定?解决问题的思路是,从多位处于平等地位的将军中选举出一位大将军,所有作战指令由大将军发出。如果这位大将军被杀,那么只需要从剩下的将军中再次选举出大将军即可。这就是解决分布式共识问题的思路。如何选举、指令如何传达则是实现分布式共识的手段。下面我们尝试推演一下这个过程。

假设拜占庭有三座城池,由3位将军掌管,每位将军都在等消息,等待了一个随机时间后,如果没收到任何消息,将派出自己的信使向另外两位将军发起自己当大将军的投票。其它将军如果收到了将军的投票请求,默认会将自己的一票投给信使最先到达的将军,后到者则拒绝。所有将军都是这个做法,那么最终必定能选出一个大将军。选出后,后面的作战指令就通过信使定期向其它将军发出,如果超过预设时间没收到指令,则认为大将军已死,苍天已死,黄天当立,剩下的将军们开始新一轮拉票当大将军活动.....

基本上,分布式共识或说分布式数据一致性大体上是按上面的思路来实现的。

分布式共识

假设我们对单一的节点就某个值进行写操作,是很容易达成共识的,毕竟只有一个节点,写成功了就达成一致。但是,如果我们有多个节点,我们该如何达成共识呢?

这个就是分布式共识问题。例如mongodb副本机制,写入一个文档是需要在所有副本节点之间进行同步的,但节点间的数据如何同步,哪个节点提供读或写服务?这些都涉及到分布式共识问题,分布式共识问题可以简单理解成在一个多节点数据集群中(此集群有可能出现分区),如何对数据进行同步,使所有节点的数据达到一致的问题。

共识算法通常具备如下特性:

  • 高可用。只要集群中多数节点是可用、与客户端的通信也是正常的,那么整个系统就是正常可用的,少数节点故障并不会影响系统的运行。

  • 强一致性。数据一致性不依赖时序,最坏的情况会产生可用性问题,但不会产生一致性问题。

Raft

raft是一个用于实现分布式共识的协议。

节点状态

在一个使用Raft共识算法的集群中,集群节点会存在三个节点状态,分别是Follwer、Candidate、Leader。

  • Follwer:接受 Leader 的心跳和日志同步数据,投票给 Candidate

  • Candidate:Leader候选角色,Follwer倒计时时钟结束转化成Candidate,可发起投票参与Leader竞选

  • Leader:集群领导角色,负责发起心跳,响应客户端,创建日志,同步日志

在一个非分区集群中,只会有一个Leader(网络分区可能会造成出现多个leader的情况),剩下的都是Follwer,Candidate只会出现在集群选举过程中,成功获取多数票的Candidate节点直接成为Leader。

任期

任期是一个连续递增的数字,每一个任期的开始都是一次选举,在选举开始时,一个或多个 Candidate 会尝试成为 Leader。如果一个 Candidate 赢得了选举,它就会在该任期内担任 Leader。如果没有选出 Leader,将会开启另一个任期,并立刻开始下一次选举。

每个节点都会存储当前的 term 号,当服务器之间进行通信时会交换当前的 term 号;如果有服务器发现自己的 term 号比其他人小,那么他会更新到较大的 term 值。如果一个 Candidate 或者 Leader 发现自己的 term 过期了,他会立即退回成 Follower。如果一台服务器收到的请求的 term 号是过期的,那么它会拒绝此次请求。

日志

  • entry:每一个事件成为 entry,只有 Leader 可以创建 entry。entry 的内容为<term,index,cmd>其中 cmd 是可以应用到状态机的操作。

  • log:由 entry 构成的数组,每一个 entry 都有一个表明自己在 log 中的 index。只有 Leader 才可以改变其他节点的 log。entry 总是先被 Leader 添加到自己的 log 数组中,然后再发起共识请求,获得同意后才会被 Leader 提交给状态机。Follower 只能从 Leader 获取新日志和当前的 commitIndex,然后把对应的 entry 应用到自己的状态机中。

Leader选举过程

开始选举时,所有节点处于Follwer状态,节点会有一个随机倒计时时钟(随机时间在150ms到300ms内),这个随机时钟是为了有节点能更快的达到Candidate状态发出选举,从而成为Leader。避免可能出现的多个节点同时成为Candidate从而导致选举效率低下问题。

当某节点election timeout心跳结束,但没收到主节点的心跳信息,它就会转成Candidate 。

此时,NodeA成为Candidate并开启亲的任期,然后向B、C节点发起投票

此时如果B、C的任期小于收到的1,自身也还没成为Candidate,此时B、C将票投到A。B、C重置election timeout时钟。在 Candidate 等待选票的时候,它可能收到其他节点声明自己是 Leader 的心跳,此时有两种情况:

  • 该 Leader 的 term 号大于等于自己的 term 号,说明对方已经成为 Leader,则自己回退为 Follower。

  • 该 Leader 的 term 号小于自己的 term 号,那么会拒绝该请求并让该节点更新 term。

收到选票的A获得集群大多数票(N/2+1),成功转成Leader,并向集群其它节点定期发送心跳(heartbeat timeout)以保住自己的Leader地位。

其他节点收到心跳(Append Entries)后响应主节点然后再次重置election timeout时钟。这个选举任期将持续到Follwer心跳time_out而成为Candidate。

主节点下线后,集群就会出现重选举,新选出的Leader的任期递增。正常情况下,获取多数票的节点成为主节点,但如果出现偶数节点时,可能会出现两个节点获取了相同票数的情况。

比如上面的情况,A、C加上自身的票数,都是2票,此时这个任期是选不出Leader的。只能重新发起一轮选举。如此反复,最终选出一个Leader。

可见,Raft协议下,节点无论是奇数还是偶数都是能正常选举出Leader的,但是偶数节点容易出现选票僵持的情况,从性能上考虑,使用奇数节点去部署集群是较好的选择。

日志复制

在上面的描述中,当集群选举出节点后,主节点会通过广播心跳到其它节点以保住自己的Leader地位,在这个过程,Leader的心跳包会携带Append Entries,这个Append Entries通常只是作心跳保持使用,但当主节点出现数据变化时,主节点在下一次的心跳中,将数据变化写到Append Entries,其它节点收到后先写到节点日志中,但数据处于uncommit状态,当然,此时主节点的数据也是uncommit,直到收到所有节点的响应,主节点的数据直接转成commit状态。

下一次主节点心跳会告诉其它节点,此数据已处于commit状态,那么其它节点也会将数据设置成commit状态。引时整个集群的数据处于一致性状态,后续再加2走同样的流程,最终集群的某个值都被设置成了7。

网络分区

当一个集群中出现了网络分区,可能会导致整个集群出现多个leader的情况,此时集群的数据一致性如何保证?

假设此时两个客户端分别通过主节点B设置x=3,主节点E设置x=8,那么集群最终x将等于8。因为在网络分区中,占少数节点的主节点因在设置值的时候未能得到大多数节点的回复(集群总节点数在集群设置完毕后就是明确的),因此x=3只是保持一个uncommit状态,并不会真的提交。

当网络恢复时,节点B、A会看到任期更高的主节点,于是将自身设置为Foller,回滚uncommit的数据并去同步主节点的数据。

此时整个集群又回到了一致性的状态。

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

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

相关文章

python升级pip的时候一直失败

如图,一直提示使用 python.exe -m pip install --upgrade pip 进行升级pip,但是执行这句命令又不成功.然后综合了几篇文章以后使用了下面的命令可以升级了 python -m pip install --upgrade pip --user -i https://mirrors.aliyun.com/pypi/simple/ 主要是在推荐的语句上使用…

解决内存泄漏问题,Profiler工具的使用介绍

什么是内存泄漏 内存泄漏&#xff08;Memory Leak&#xff09;是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放&#xff0c;造成系统内存的浪费&#xff0c;导致程序运行速度减慢甚至系统崩溃等严重后果。 以上是官方针对内存泄漏的说法。说的通俗一点&#x…

高频SQL50题(基础版)-3

文章目录 主要内容一.SQL练习题1.1174-即时食物配送代码如下&#xff08;示例&#xff09;: 2.550-游戏玩法分析代码如下&#xff08;示例&#xff09;: 3.2356-每位教师所教授的科目种类的数量代码如下&#xff08;示例&#xff09;: 4.1141-查询近30天活跃用户数代码如下&…

【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现

目录 Ⅰ. 实践说明 0x00 计数器&#xff08;Counter&#xff09; 0x01 异步计数器&#xff08;Asynchronous Counter&#xff09; 0x02 同步计数器&#xff08;Synchronous Counter&#xff09; Ⅱ. 实践&#xff1a;2位二进制计数器 0x00 实践说明 0x01 输出表 0x02 代…

由于找不到dll无法执行代码的解决方法,深度解析5个dll修复方法

在使用计算机的过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到dll无法执行代码”。这个错误通常发生在程序运行时&#xff0c;系统无法找到所需的动态链接库&#xff08;DLL&#xff09;文件。这个问题可能由多种原因引起&#xff0c;包括缺少…

前端如何结合mock模拟假数据

由于某人不想写后端接口&#xff0c;不想用真数据对接vue-element-admin框架&#xff0c;用以前的接口&#xff0c;改token有点点麻烦&#xff0c;所以咱试试mock.js

《算法通关村——透彻理解二叉树中序遍历的应用》

《算法通关村——透彻理解二叉树中序遍历的应用》 直接上题 108. 将有序数组转换为二叉搜索树 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高…

【电工基础】

电工基础 11.1 简介1.2 电路作用1.3 电路模型1.4 电流定义1.5 电压定义1.6 电动势1.7 电阻元件1.7.1 电阻元件定义1.7.2 电阻原件的特性1.7.31.7.4 1.81.91.10 345 1 1.1 简介 电源外部&#xff0c;正电荷移动的方向是由电源正极向电源负极方向&#xff0c;负电荷移动的方向是…

GEE:遥感影像二值化

作者:CSDN @ _养乐多_ 在Google Earth Engine(GEE)中,图像二值化是将图像中的像素值转换为二进制(0或1)的过程。这通常用于将连续的遥感图像转换为只有两个值的二值图像,以突出图像中的特定特征或区域。 结果如下图所示,将NDVI图像中,大于0.3的值设置为1(黑色),小…

VBA_MF系列技术资料1-217

MF系列VBA技术资料 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-04属于定…

超详细的性能测试流程

一、性能测试概念 我们经常看到的性能测试概念&#xff0c;有人或称之为性能策略&#xff0c;或称之为性能方法&#xff0c;或称之为性能场景分类&#xff0c;大概可以看到性能测试、负载测试、压力测试、强度测试等一堆专有名词的解释。 针对这些概念&#xff0c;我不知道你…

Harbor了解及部署

Harbor 无论是使用Docker-distribution去自建仓库&#xff0c;还是通过官方镜像跑容器的方式去自建仓库&#xff0c;通过前面的演示我们可以发现其是非常的简陋的&#xff0c;还不如直接使用官方的Docker Hub去管理镜像来得方便&#xff0c;至少官方的Docker Hub能够通过web界…

认识继承和多态

1 继承 1.1 为什么需要继承 Java 中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是现实世界错综复杂&#xff0c;事物之间可能会存在一些关联&#xff0c;那在设计程序里就需要考虑 比如&a…

赶紧收藏!阿里内部使用的127页k8s实战手册,不能再详细了!

2022 年 12 月 8 号Kubernetes 发布了1.26新版本&#xff0c;此版本中有两个突出的新功能&#xff0c;它们有可能改变用户与 Kubernetes 交互的方式&#xff0c;此外&#xff0c;其他功能将使集群管理员的工作更轻松。 说起来&#xff0c;Kubernetes从诞生初期就广泛受到业界的…

英国访问学者类型签证详解

近年来&#xff0c;英国作为世界上优秀的学术研究中心之一&#xff0c;吸引了众多国际学者的目光。为了促进国际学术交流&#xff0c;英国设立了多种类型的访问学者签证&#xff0c;以满足不同学者的需求。在本文中&#xff0c;我们将深入探讨英国访问学者类型签证及其特点。 1…

金字塔原理小节

目录 第1章 为什么要用金字塔结构 一、归类分组&#xff0c;将思想组织成金字塔 二、奇妙的数字“7” 三、归类分组搭建金字塔 四、找出逻辑关系&#xff0c;抽象概括 五、自上而下表达&#xff0c;结论先行 第1章 为什么要用金字塔结构 如果受众希望通过阅读你的文章、听…

osg点云加载与渲染

目录 效果 laslib 关键代码 完整代码 效果 las点云读取使用了laslib这个库。 laslib 关键代码 {// 这里演示读取一个 .txt 点云文件const char* lasfile path.c_str();std::ifstream ifs;ifs.open(lasfile, std::ios::in | std::ios::binary);liblas::ReaderFactory f;libl…

MySQL数据库基础和操作

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; MYSQL数据库 &#x1f319;请不要相信胜利就像山坡上的蒲公英一…

C++ 开发【深入浅出】笔记02

多态 同一种类型的不同表现形式基类指针指向基类对象基类对象调用的成员函数&#xff0c;基类指针指向派生类对象则调用派生类得成员函数&#xff0c;这种现象就称为多态构成多态的条件 继承关系基类多态函数必须声明为虚函数&#xff08;virtual&#xff09;派生类必须覆盖&am…

【原创课设】java+swing+mysql药店管理系统设计与实现

摘要&#xff1a; 药店管理系统对于药店运营具有重大的意义。首先&#xff0c;它可以提高药店的运营效率&#xff0c;减少人工操作成本&#xff0c;通过信息化的管理方式&#xff0c;可以提高药店的服务质量和管理水平&#xff0c;增强药店的市场竞争力。用户可以登录系统直接…