Raft 算法总结——关于选举和心跳

本文是 MIT6.824 Lab-2A 涉及到的 Raft 算法的总结,主要涉及到

  1. Leader 的选举
  2. 心跳(不包括状态机日志复制)

其余部分将在后续做相应的实验的时候进行更新

什么是 Raft

Raft 算法是一种分布式一致性共识算法

什么是分布式一致性共识算法

在分布式系统理论中,有著名的 CAP 理论(Consistency-Availability-Partition tolerance Theory)

  1. C:Consitency,一致性。该项强调数据的正确性. 具体而言,每次读操作,要么读到最新,要么读失败. 这要求整个分布式系统像是一个不可拆分的整体,写操作作用于集群像作用于单机一样,具有广义的"原子性".
  2. A:Availability,可用性。该项站在使用者的角度,强调使用服务的体验.客户端的请求能够得到响应,不发生错误,也不能出现过长的等待时间.
  3. P:Partition tolerance,分区容错性。分区容错性强调的是,在网络环境不可靠的背景下,整个系统仍然是正常运作的,不至于出现系统崩溃或者秩序混乱的局面.

CAP 理论强调的是,一个系统中,C、A、P 三项性质至多只能满足其二,即每个系统依据其架构设计会具有 CP、AP 或者 CA 的倾向性.

分布式一致性共识算法指的是在分布式系统中,使得所有节点对同一份数据的认知能够达成共识的算法.

可以看到,不论是命名还是概述,都在突出其实现目标在于 C,即数据一致性. 然而,在 1.5 小节中我们已谈及,倘若基于写请求 + 数据同步串行化的方式进行实施,实际上是可以满足强 C 的,但是对应的 A 就会破坏得支离破碎.

因此,分布式一致性共识算法,实际上是在基于各种精妙的算法机制,能够在尽可能少地牺牲 C 的基础之上,将 A 提升到尽可能高的水平.

我们今天的主角 Raft 算法扮演的正是这样一个角色.

Raft 的一些概念

一主多从

在 raft 算法中节点会分为 一个 Leader ,和 多个 Follower ,(这里暂时忽略 Candidate)其中

  • Leader 负责处理客户端的写请求复制日志 (将数据同步给 Follower 节点),发布心跳(维持其领导地位)
  • Follower 负责响应客户端的读请求接收Leader发送的日志项,并将其存储在本地日志中,保持与Leader相同的日志顺序选举投票

多数派原则

多数派原则指的是,系统的决断无需全员参与 ,多数派达成的共识即可视为整个系统的答复。

举个例子:假设一个集群存在 5 个节点。如果客户端发送了一个写请求给 Leader。在 Raft 算法中,由于多数派原则的存在,那么这个写入的日志只需要被写入到集群中的多数,也即 3 个节点中(包括 Leader),就可以认为该数据已经被成功写入。

多数派原则将会贯穿 raft 算法的始终,例如我们下面要介绍的选举日志复制 等等

其他概念在 Lab-2A 中暂时还不是很重要,我们将在另外的文章中提及。

任期(Term)

在Raft共识算法中,Term(任期)是一个重要的概念,用于标识系统中的不同时间段。每个任期都有一个唯一的正整数标识,它在整个系统中用于区分不同的时期。

  • 一个Term内只能有一个Leader,当一个节点成为Leader时,它的Term会增加。
  • 任期的引入有助于防止过时信息的影响。在Raft中,节点在进行投票、处理心跳等操作时,会比较Term的大小,只有当Term更大的信息才会被接受,从而防止过时的信息对系统造成不一致性。

总体而言,Raft中的Term是一种用于标识时间段和协调节点之间通信的机制,有助于确保系统的一致性和正确性。每次发生选举时,都会引入一个新的Term,确保系统在不同的时间段有清晰的状态。

Raft 算法中的选举

选举在干些什么?

  • 前面我们提到,在 Raft 算法中,有 Leader 和 Follower 的区分,而且 Leader 是必须存在且唯一的。
  • 那么 Raft 算法的选举就是要保证在每个时间段中,集群中都有唯一的 Leader 存在 ,并且在网络分区、节点故障或其他异常情况下,系统仍然能够维持一致性。当Raft系统中的Leader节点出现问题(例如崩溃或无法正常通信)时,其他节点会通过一轮选举来选举新的Leader

选举的过程

Leader 是怎么上任的

在节点初始化时,每个节点都会被初始化为 Follower 。

在 Raft 算法中,有两个时间来控制选举,第一个是 election timeout , election timeout是指追随者在成为候选人之前等待的时间。election timeout 被随机分配为150毫秒到300毫秒之间。

关于"election timeout 被随机分配为150毫秒到300毫秒",这里的随机目的是什么,为什么不给出一个具体的值?

  1. 引入随机的election timeout是为了避免出现多个节点同时发起选举的情况,从而降低冲突的概率。如果所有的节点都在相同的固定时间间隔内成为候选人,它们可能会同时发起选举并请求投票。这可能导致投票分散,难以达到选举的多数派要求。
  2. 通过引入随机性,每个节点的election timeout在一个范围内波动,就会导致节点在不同的时间点成为候选人,减少了竞争的激烈程度。这样,系统中的节点更有可能依次成为候选人,并且每个节点的选举时间点会有所不同。
  1. 当节点被初始化之后,就会启动一个定时器,定时器被触发,也就是 election timeout 到期之后,Follower 就会变成 Candidate (候选人) ,并且开启一个新的任期(term,此时选举便正式开始了

    **关于 Candidate(候选人):**在 Raft 算法中,Follower 要成为 Leader 必须先成为一个 Candidate ,Candidate 会向其他节点发送投票请求,请求其他节点投票支持自己成为新的 Leader。如果一个 Candidate 获得大多数节点的选票,它将成为新的 Leader

  2. Candidate 开启一个新的 term 之后干的第一件事情,就是把自己的那一票投给自己。紧接着,它会发送 Request Vote(投票请求)给集群内的其他节点,请求其他节点将票投给自己。

  3. 如果收到 Request Vote的节点在当前任期内还没有把票投出去,那么他会把票投给当前候选人。并且重置自己的 election timeout

    这里要说明一下投票响应的规则:

    1. 如果接收到的投票请求中的term小于等于节点当前的term,节点会拒绝投票。
    2. 如果节点还没有为当前term投过票,它会投票给候选人。
    3. 如果节点已经投过票给其他候选人,它会拒绝再次投票。 至于为什么要制定这样的规则,请参考论文
  4. 一旦 Candidate 收到多数派节点的选票,那么他就会成为新的 Leader

值得注意的是,即使每个节点的 election timeout都是随机的,但也有可能出现两个节点同时开始选举的情况,这时还是会出现两个节点都无法拿到多数派选票,无法成功上任。 针对这种情况,Raft 采取的措施是节点直接等待一轮新的选举开始

Leader 怎么维持其领导地位?它要是挂了怎么办?

前面我们提到,"在 Raft 算法中,有两个时间来控制选举"。我们一个知道其中一个是 election timeout ,那么另外一个就是 heartbeat timeout

  1. Candidate 当选为 Leader 之后,该节点就会开始维护一个心跳 ,每次触发心跳,Leader 就会发送一个 Append Entries 给其他节点。

  2. Follower 接收到 Append Entries 会重置自身的 election timeout,防止在 Leader 没有出现异常的情况下开启新一轮的选举。值得注意的是,在下面这几种情况中,Follower 不能重置 election timeout

    • 心跳发起者的任期已经过时了,也就是args.PrevLogTerm < rf.currentTerm,这种情况可能出现在出现网络屏障后恢复,此时已经有新的 Leader 出现,例如下图中,AB 和 CDF 中间出现了网络屏障,此时 CDF 中选举出了新的 Leader D.那么当网络屏障消失之后,B 发送心跳请求给 C/D/F 时,会发现自己的任期已经落后了,此时 A 自己卸任成文 Follower

关于 Append Entries 的作用:

  1. 日志复制: 当领导者产生新的日志条目时,它将这些新条目包含在 "Append Entries" 消息中发送给跟随者。跟随者接收到这些消息后,会将领导者的日志条目追加到自己的日志中,从而保持日志的一致性。

  2. 心跳功能: "Append Entries" 消息也用作心跳。在Raft中,领导者定期发送空的 "Append Entries" 消息给跟随者,起到一种心跳的作用。如果跟随者在一定时间内没有收到领导者的心跳消息,就可能认为领导者已经失效,触发新一轮的选举。 这里我们暂时只讨论它作为心跳的功能。

  1. 如果Leader接收到Follower返回的信息,发现自己过时了,那么需要切换自己的角色为Follower

  2. 如果Leader接收到Follower返回的正常信息,那么只需要正常的等待发送下一轮心跳就可以了。(解决了"Leader 怎么维持其领导地位"的问题)

  3. 如果 Follower 在一个 election timeout 周期内,都没有收到任何心跳请求,那么Follower就会成为Candidate 参加竞选.(解决了"它要是挂了怎么办"的问题)

因此在 Raft 算法中 election timeout > heartbeat timeout

写在最后

  • 至此,Raft算法中的选举部分我们就讲了个七七八八,至于Lab-2A的具体实现细节,将会在下一篇文章中讲到.
  • 本文只是很粗糙的讲了一下选举的过程,里面很多细节都没详细展开,比如:
    1. 为什么节点的投票规则是这样规定的?
    2. 为什么是多数派原则,而不是等全部节点通过?
  • 读者可以自己在原始论文中找到这些答案.
  • 同样的,我们也没有对 Raft 算法下的外部请求链路,状态机,两阶段提交,日志索引,预写日志等做出解释,这将在后面的 lab 中给出.

参考资料

相关推荐
hello早上好28 分钟前
BeanFactory 实现
后端·spring·架构
fail_to_code35 分钟前
递归法的递归函数何时需要返回值
算法
白宇横流学长40 分钟前
基于J2EE架构的在线考试系统设计与实现【源码+文档】
java·架构·java-ee
C137的本贾尼1 小时前
(每日一道算法题)二叉树剪枝
算法·机器学习·剪枝
BUG收容所所长2 小时前
栈的奇妙世界:从冰棒到算法的华丽转身
前端·javascript·算法
XRZaaa2 小时前
常见排序算法详解与C语言实现
c语言·算法·排序算法
G探险者2 小时前
《深入理解 Nacos 集群与 Raft 协议》系列五:为什么集群未过半,系统就不可用?从 Raft 的投票机制说起
分布式·后端
G探险者2 小时前
《深入理解 Nacos 集群与 Raft 协议》系列一:为什么 Nacos 集群必须过半节点存活?从 Raft 协议说起
分布式·后端
@我漫长的孤独流浪2 小时前
数据结构测试模拟题(4)
数据结构·c++·算法
G探险者2 小时前
《深入理解 Nacos 集群与 Raft 协议》系列四:日志复制机制:Raft 如何确保提交可靠且幂等
分布式·后端