Raft 算法—Leader选举、Log复制

1. 复制状态机

在这里插入图片描述(1)客户端向服务器发送一条命令;
(2)服务器上的共识模块将接收到的命令添加到自己的 log 中,然后和其他服务器上的共识模块通信,以复制该命令到其他服务器上;
(3)一旦命令被成功复制到大多数服务器上之后,每个服务器上的状态机将按序执行 log 中的命令;
(4)状态机输出并返回命令的执行结果。

2. Raft基础

集群角色

Raft 集群中的节点按角色可划分为:leader、follower 和 candidate。

(1)正常情况下,集群中只存在一个 leader,并由 leader 负责处理所有的客户端请求。
(2)follower 是被动式的,它们不会主动发出请求,相反,它们只是简单地响应来自 leader 和 candidate 的请求;此外,如果 follower 接收到来自客户端的请求,它们会将请求重定向到 leader;集群中所有节点的初始角色都是 follower。
(3)candidate 即是 leader 的候选者。

term

Raft 将时间划分为任意长度的多个 term,并使用连续的整数来标识每个 term。

每个 term 都以一次选举(选出 leader)开始。如果某个 candidate 赢得了选举(得到了大多数的票数),则它将成为当前 term 余下时间中的 leader。如果没有 candidate 赢得选举(多个 candidate 获得了相同的票数),则此 term 中没有 leader,并开始下一个 term。

在这里插入图片描述

term 的作用是充当一个逻辑时钟。每个服务器都会有自己的 current term 序号,且 current term 是随着时间单调递增的。

(1)服务器 A 与服务器 B 进行通信时,双方都会携带上自己的 current term,如果服务器 A 的 current term 小于服务器 B 的 current term,则服务器 A 会更新其 current term 为服务器 B 的 current term,反之亦然。

(2)如果 candidate 或 leader 发现其 current term 不是最大的,则它们会立即切换回 follower 状态。

(3)如果服务器接收到的请求的 current term 小于服务器的 current term,则服务器会拒绝该请求。

3. Leader 选举

(1)初始时,每个服务器都是 follower。
(2)如果 follower 在选举超时定时器到期前接收到来自 leader 或 candidate 的有效 RPC,则继续处于 follower 状态。
(3)如果 follower 在选举超时定时器到期后仍未接收到来自 leader 或 candidate 的有效 RPC,则它会认为当前没有 leader,并开始新的选举:递增其 current term 号,然后转换到 candidate 状态,接着投它自己一票,然后并行地向其他服务器发出 RequestVote RPC。在一个 term 中,每个服务器最多只能为一个 candidate 投出一票,且以先来先得的方式给出选票。
(4)如果 candidate 赢得了大多数的选票,则它将成为新的 leader,并向其他的服务器发送心跳以维持其 leader 身份。
(5)如果 candidate 在等待选票的期间接收到了来自其他服务器的 AppendEntries RPC 以宣告 leader 的存在,且该 leader 的 term 号大于等于该 candidate 的 current term 号,则 candidate 承认其 leader 身份,并切换回 follower 状态;否则,该 candidate 拒绝该 RPC 并继续处于 candidate 状态。
(6)如果存在多个 candidate,且没有哪个 candidate 获得超过半数的选票,则结果是所有 candidate 都会超时,然后开始下一次选举。为了避免此类情况的频繁出现,每个服务器所使用的定时器的超时时间均是随机的,所以某个时刻通常只有一个服务器会出现超时。candidate 会在选举开始时重启其选举超时定时器,并在超时后开始新的一次选举。

在这里插入图片描述

4. Log 复制

复制过程

(1)leader 会将收到的客户命令当作新的 entry,并追加到其 log 中;然后并行地向所有其他的服务器发起 AppendEntries RPC,以复制该 entry 到其他服务器上。如果 follower 没有给出响应,则 leader 会持续地向该 follower 发送 AppendEntries RPC,直到成功。

log 的组织形式如下:

在这里插入图片描述

每条 entry 都包含了一条状态机命令、接收到该命令时 leader 的 term 号、该 entry 在 log 中的index。

(2)当一条 entry 被复制到大多数节点上之后,leader 的状态机便会执行其中的命令,并将执行结果返回给客户端。这样的 entry 称为 committed,即被提交了。

(3)leader 会跟踪需要被提交的所有 entry 中 index 的最大值,并将该 index 包含在后续的 AppendEntries RPC 中;当 follower 得知一条 entry 已被 leader 提交后,该 follower 也会以相同的顺序提交该 index 及其之前所有未被提交的 entries。

一致性检查

(1)leader 在 AppendEntries RPC 中也会包含新 entries 之前的那条 entry 的 index 和 term 号;如果 follower 没有在自己的 log 中找到具有相同 index 和 term 号的 entry,则它会拒绝添加新的 entries。(例如,leader 崩溃前没有即时将 entries 复制到其他节点,从而导致 log 不一致。)

(2)leader 也会为每个服务器维护一个 nextIndex 变量,其表示将要被复制到该服务器上的下一条 entry 的 index(nextIndex 对应的 entry 对 follower 来说就是新 entry);nextIndex 的初始值为 leader 中 log 最后一条 entry 之后的一个 index。如果一致性检查失败,导致 follower 拒绝添加新的 entries,leader 会递减相应的 nextIndex,然后发送新的 AppendEntries RPC,其中包含更新后的新 entry 的 index 和 term 号。当 leader 和 follower 最终达成一致时,follower 会移除该 index 之后的所有 entries,然后接受 leader 发送过来的新的 entries。

5. 安全性

选举限制

对于服务器 A 和服务器 B 来说,如果 A 的 log 中的最后一条 entry 的 term 号大于 B 的 log 中的最后一条 entry 的 term 号,则 A 的 log 比 B 的 log 新;如果两者的 term 号相等,则 index 大(log 更长)的一方较新。

(1)一个 candidate 如果不包含所有已提交的 entries,则它是没有机会赢得 leader 选举的。
(2)RequestVote RPC 中会包含 candidate 的 log 的有关信息,如果 candidate 的 log 没有比投票者的 log 要新,则投票者会拒绝将票投给该 candidate。 因为一个 candidate 需要赢得大多数节点的选票,而这些节点当中一定至少有一个节点包含所有已提交的 entries;因此,如果一个 candidate 赢得了选举,则说明它包含了所有已提交的 entries。

提交问题

Raft 规定只有当前 term 中的 entries 才能够根据计算副本数的原则来提交 entries, 即,将 entries 复制到大多数节点上之后就提交该 entries。对于之前 term 中的 entries 则不适用此规则。这主要是为了防止下述情况:

在这里插入图片描述
(a)S1 为 leader,且已经复制了 index 为 2 的 entry 到部分节点上。
(b)S1 崩溃,S5 成为 leader,并且接受了 index 为 2 的不同的 entry。
(c)S5 崩溃,S1 恢复,并继续担任 leader,然后继续复制 index 为 2 的 entry 到其他节点上,且已超过半数,但此时 leader 还未提交该 entry。
(d)S1 崩溃,S5 恢复,并继续担任 leader,且使用其之前的 entry 覆盖了其他节点上 index 为 2 的 entry。
(e)S1 在崩溃前复制 term 为 4 的 entry 到大多数节点上并提交(term 为 2 的 entry 也相应地被提交),则 S5 没有资格成为新的 leader。

在(c)中,如果 S1 根据计算副本数的原则提交了 term 为 2 的 entry,然后崩溃了;当 S5 成为 leader 后,用新的的 entry 覆盖之前 term 为 2 的 entry,而该 entry 已被其他节点提交了,此时就会导致错误。因此正确的做法是,继续复制 term 为 4 的 entry,然后提交 term 为 4 的 entry,则连带着将 term 为 2 的 entry 也提交了(前提是 S1 没有那么早就崩溃;即使崩溃了也没事,因为 term 为 2 的 entry 还没有被提交)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值