Raft 算法属于 Multi-Paxos 算法,它是在兰伯特 Multi-Paxos 思想的基础上,做了一些简 化和限制,比如增加了日志必须是连续的,只支持领导者、跟随者和候选人三种状态,在理 解和算法实现上都相对容易许多。

除此之外,Raft 算法是现在分布式系统开发首选的共识算法。绝大多数选用 Paxos 算法的 系统(比如 Cubby、Spanner)都是在 Raft 算法发布前开发的,当时没得选;而全新的系统大多选择了 Raft 算法(比如 Etcd、Consul、CockroachDB)。

对你来说,掌握这个算法,可以得心应手地处理绝大部分场景的容错和一致性需求,比如分 布式配置系统、分布式 NoSQL 存储等等,轻松突破系统的单机限制。

如果要用一句话概括 Raft 算法,我觉得是这样的:从本质上说,Raft 算法是通过一切以 领导者为准的方式,实现一系列值的共识和各节点日志的一致。 这句话比较抽象,我来做个 比喻,领导者就是 Raft 算法中的霸道总裁,通过霸道的“一切以我为准”的方式,决定了 日志中命令的值,也实现了各节点日志的一致。

假设我们有一个由节点 A、B、C 组成的 Raft 集群(如图所示),因为 Raft 算法一切以领 导者为准,所以如果集群中出现了多个领导者,就会出现不知道谁来做主的问题。在这样一 个有多个节点的集群中,在节点故障、分区错误等异常情况下,Raft 算法如何保证在同一 个时间,集群中只有一个领导者呢?带着这个问题,我们正式进入今天的学习。

成员身份,又叫做服务器节点状态,Raft 算法支持领导者(Leader)跟随者 (Follower)候选人 (Candidate) 3 种状态。为了方便讲解,我们使用不同的图形表 示不同的状态。在任何时候,每一个服务器节点都处于这 3 个状态中的 1 个。

跟随者:就相当于普通群众,默默地接收和处理来自领导者的消息,当等待领导者心跳 信息超时的时候,就主动站出来,推荐自己当候选人。

候选人:候选人将向其他节点发送请求投票(RequestVote)RPC 消息,通知其他节点 来投票,如果赢得了大多数选票,就晋升当领导者。

领导者:蛮不讲理的霸道总裁,一切以我为准,平常的主要工作内容就是 3 部分,处理 写请求、管理日志复制和不断地发送心跳信息,通知其他节点“我是领导者,我还活 着,你们现在不要发起新的选举,找个新领导者来替代我。”

Raft 算法是强领导者模型,集群中只能有一个“霸道总裁”。

选举领导者的过程

首先,在初始状态下,集群中所有的节点都是跟随者的状态。

Raft 算法实现了随机超时时间的特性。也就是说,每个节点等待领导者节点心跳信息的超 时时间间隔是随机的。通过上面的图片你可以看到,集群中没有领导者,而节点 A 的等待 超时时间小(150ms),它会先因为没有等到领导者的心跳信息,发生超时。

这个时候,节点 A 就增加自己的任期编号,并推举自己为候选人,先给自己投上一张选 票,然后向其他节点发送请求投票 RPC 消息,请它们选举自己为领导者。

如果其他节点接收到候选人 A 的请求投票 RPC 消息,在编号为 1 的这届任期内,也还没有 进行过投票,那么它将把选票投给节点 A,并增加自己的任期编号。

如果候选人在选举超时时间内赢得了大多数的选票,那么它就会成为本届任期内新的领导者。

节点 A 当选领导者后,他将周期性地发送心跳消息,通知其他服务器我是领导者,阻止跟 随者发起新的选举,篡权。

讲到这儿,你是不是发现领导者选举很容易理解?与现实中的议会选举也蛮类似?当然,你 可能还是对一些细节产生一些疑问:

  • 节点间是如何通讯的呢?
  • 什么是任期呢?
  • 选举有哪些规则?
  • 随机超时时间又是什么?

选举过程四连问
老话说,细节是魔鬼。这些细节也是很多同学在学习 Raft 算法的时候比较难掌握的,所以 我认为有必要具体分析一下。咱们一步步来,先来看第一个问题。

节点间如何通讯?

在 Raft 算法中,服务器节点间的沟通联络采用的是远程过程调用(RPC),在领导者选举 中,需要用到这样两类的 RPC:

  • 请求投票(RequestVote)RPC,是由候选人在选举期间发起,通知各节点进行投票;
  • 日志复制(AppendEntries)RPC,是由领导者发起,用来复制日志和提供心跳消息。

我想强调的是,日志复制 RPC 只能由领导者发起,这是实现强领导者模型的关键之一,希 望你能注意这一点,后续能更好地理解日志复制,理解日志的一致是怎么实现的。

什么是任期?

我们知道,议会选举中的领导者是有任期的,领导者任命到期后,要重新开会再次选举。 Raft 算法中的领导者也是有任期的,每个任期由单调递增的数字(任期编号)标识,比如 节点 A 的任期编号是 1。任期编号是随着选举的举行而变化的,这是在说下面几点:

  • 跟随者在等待领导者心跳信息超时后,推举自己为候选人时,会增加自己的任期号,比 如节点 A 的当前任期编号为 0,那么在推举自己为候选人时,会将自己的任期编号增加 为 1

  • 如果一个服务器节点,发现自己的任期编号比其他节点小,那么它会更新自己的编号到 较大的编号值。比如节点 B 的任期编号是 0,当收到来自节点 A 的请求投票 RPC 消息 时,因为消息中包含了节点 A 的任期编号,且编号为 1,那么节点 B 将把自己的任期编 号更新为 1。

我想强调的是,与现实议会选举中的领导者的任期不同,Raft 算法中的任期不只是时间 段,而且任期编号的大小,会影响领导者选举和请求的处理。

  • 在 Raft 算法中约定,如果一个候选人或者领导者,发现自己的任期编号比其他节点小, 那么它会立即恢复成跟随者状态。比如分区错误恢复后,任期编号为 3 的领导者节点 B,收到来自新领导者的,包含任期编号为 4 的心跳消息,那么节点 B 将立即恢复成跟 随者状态。

  • 还约定如果一个节点接收到一个包含较小的任期编号值的请求,那么它会直接拒绝这个 请求。比如节点 C 的任期编号为 4,收到包含任期编号为 3 的请求投票 RPC 消息,那么它将拒绝这个消息。

在这里,你可以看到,Raft 算法中的任期比议会选举中的任期要复杂。同样,在 Raft 算法 中,选举规则的内容也会比较多。

选举有哪些规则

在议会选举中,比成员的身份、领导者的任期还要重要的就是选举的规则,比如一人一票、 弹劾制度等。“无规矩不成方圆”,在 Raft 算法中,也约定了选举规则,主要有这样几 点。

  • 领导者周期性地向所有跟随者发送心跳消息(即不包含日志项的日志复制 RPC 消息), 通知大家我是领导者,阻止跟随者发起新的选举。

  • 如果在指定时间内,跟随者没有接收到来自领导者的消息,那么它就认为当前没有领导 者,推举自己为候选人,发起领导者选举。

  • 在一次选举中,赢得大多数选票的候选人,将晋升为领导者。

  • 在一个任期内,领导者一直都会是领导者,直到它自身出现问题(比如宕机),或者因 为网络延迟,其他节点发起一轮新的选举。

  • 在一次选举中,每一个服务器节点多会对一个任期编号投出一张选票,并且按照“先 来先服务”的原则进行投票。比如节点 C 的任期编号为 3,先收到了 1 个包含任期编号 为 4 的投票请求(来自节点 A),然后又收到了 1 个包含任期编号为 4 的投票请求(来 自节点 B)。那么节点 C 将会把唯一一张选票投给节点 A,当再收到节点 B 的投票请求 RPC 消息时,对于编号为 4 的任期,已没有选票可投了。

    当任期编号相同时,日志完整性高的跟随者(也就是后一条日志项对应的任期编号值 更大,索引号更大),拒绝投票给日志完整性低的候选人。比如节点 B、C 的任期编号 都是 3,节点 B 的后一条日志项对应的任期编号为 3,而节点 C 为 2,那么当节点 C 请求节点 B 投票给自己时,节点 B 将拒绝投票。

我想强调的是,选举是跟随者发起的,推举自己为候选人;大多数选票是指集群成员半数以 上的选票;大多数选票规则的目标,是为了保证在一个给定的任期内多只有一个领导者。

其实在选举中,除了选举规则外,我们还需要避免一些会导致选举失败的情况,比如同一任 期内,多个候选人同时发起选举,导致选票被瓜分,选举失败。那么在 Raft 算法中,如何 避免这个问题呢?答案就是随机超时时间。

如何理解随机超时时间

在议会选举中,常出现未达到指定票数,选举无效,需要重新选举的情况。在 Raft 算法的 选举中,也存在类似的问题,那它是如何处理选举无效的问题呢?

其实,Raft 算法巧妙地使用随机选举超时时间的方法,把超时时间都分散开来,在大多数 情况下只有一个服务器节点先发起选举,而不是同时发起选举,这样就能减少因选票瓜分导 致选举失败的情况。

我想强调的是,在 Raft 算法中,随机超时时间是有 2 种含义的,这里是很多同学容易理解 出错的地方,需要你注意一下:

  1. 跟随者等待领导者心跳信息超时的时间间隔,是随机的;
  2. 当没有候选人赢得过半票数,选举无效了,这时需要等待一个随机时间间隔,也就是 说,等待选举超时的时间间隔,是随机的。

Raft 算法详解(一)领导者选举相关推荐

  1. 【面试】Raft算法详解

    文章目录 前言 一.Raft算法概述 二.Leader选举 三.日志同步 四.安全性 五.日志压缩 六.成员变更 七.Raft与Multi-Paxos的异同 八.Raft算法总结 参考 前言 Paxo ...

  2. Raft协议详解(一)前言:子问题分解

    分布式一致性,一直是分布式系统中非常重要的部分.在多机集群中,如何保证不同服务器上同一副本的数据是一致正确的,如何保证在故障频发的集群中数据能够安全保存等问题,都需要靠分布式一致性来解决.在对分布式一 ...

  3. Matlab人脸检测算法详解

    这是一个Matlab人脸检测算法详解 前言 人脸检测结果 算法详解 源代码解析 所调用函数解析 bwlabel(BW,n) regionprops rectangle 总结 前言 目前主流的人脸检测与 ...

  4. 图论-最短路Dijkstra算法详解超详 有图解

    整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路.(不像SPFA,玄学复杂度) 但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂. ...

  5. C++中的STL算法详解

    1.STL算法详解 STL提供能在各种容器中通用的算法(大约有70种),如插入.删除.查找.排序等.算法就是函数模板,算法通过迭代器来操纵容器中的元素.许多算法操作的是容器上的一个区间(也可以是整个容 ...

  6. 粒子群(pso)算法详解matlab代码,粒子群(pso)算法详解matlab代码

    粒子群(pso)算法详解matlab代码 (1)---- 一.粒子群算法的历史 粒子群算法源于复杂适应系统(Complex Adaptive System,CAS).CAS理论于1994年正式提出,C ...

  7. 基础排序算法详解与优化

    文章图片存储在GitHub,网速不佳的朋友,请看<基础排序算法详解与优化> 或者 来我的技术小站 godbmw.com 1. 谈谈基础排序 常见的基础排序有选择排序.冒泡排序和插入排序.众 ...

  8. 目标检测 RCNN算法详解

    原文:http://blog.csdn.net/shenxiaolu1984/article/details/51066975 [目标检测]RCNN算法详解 Girshick, Ross, et al ...

  9. Twitter-Snowflake,64位自增ID算法详解

    Twitter-Snowflake,64位自增ID算法详解 from: http://www.lanindex.com/twitter-snowflake%EF%BC%8C64%E4%BD%8D%E8 ...

最新文章

  1. 太嚣张了!会Python的人!
  2. (转载)IE 浏览器的创新
  3. 日常生活小技巧 -- win10造字
  4. An easy problem(hdu2055)
  5. P7988-[USACO21DEC] HILO G【set,线段树】
  6. Shiro————会话管理
  7. 使用sqlyog创建数据库
  8. 动态对象泛型数组绑定控件 0107
  9. [译] 关于 HTTP/3 的一些心得
  10. C++新特性探究(十三):右值引用(r-value ref)探究
  11. shiro学习笔记:remeberMe,多次登录锁死账号
  12. 怎么用U盘重装系统?
  13. 2019 世界读书日,让程序员疯狂的 13 本豆瓣高分技术书!
  14. Mac 16进制编辑器Hex Friend
  15. ffmpeg之让视频快进
  16. android 自定义圆形进度条,Android自定义控件实现圆形进度条
  17. 【洛谷】P4147 玉蟾宫 解题报告
  18. Derivation of Linear Regression with One Variable
  19. x射线计算机断层摄影设备参数,GB 17589—2011 X射线计算机断层摄影装置质量保证检测规范.pdf...
  20. cesium获取模型高度_180套经典夹具设计方案(附详解+模型),原来夹具设计这么简单!...

热门文章

  1. 理解maven命令package、install、deploy的联系与区别
  2. 想体验.NET7又不想安装体验版,Windows沙盒了解一下
  3. Caffe学习笔记(二):Caffe前传与反传、损失函数、调优
  4. 已经清空了垃圾箱怎样找回误删的文件
  5. Android AOA链接(accessory host)
  6. MATLAB 中出现 Undefined variable py or function py.command 错误
  7. 智慧全媒体 5G新视听,共探新时代广播电视!
  8. 优酷路由宝增加php,优酷路由宝旗舰版YK-L2刷改华硕[N14U N54U]5G 2G的7620老毛子Padavan固件方法...
  9. 人为回环SLAM-Human-in-the-Loop SLAM
  10. 量子力学 or 线性代数(Stern-Gerlach实验)?