Raft领导者变更的安全性

文章讲述了Raft算法在领导者变更时如何处理不完整的日志,强调了日志的安全性和一致性,包括延迟提交策略以及no-op空日志的使用,以确保状态机的正确执行。

领导者的变更

新的领导者上任后,由于前一任领导者的日志可能未提交,导致日志变得不干净。Raft算法在新的领导者上任时,对于冲突的日志不进行处理。而是在正常运行过程中,进行日志处理。
Raft算法假定领导者的日志始终是对的,领导者要做的是,在日志复制过程中,让所有跟随者的日志与之匹配。
在这里插入图片描述
可以看到,从索引为4的日志后,系统中的日志杂乱不堪。

分析上图,可以得到,S4、S5是任期2,3,4的领导者(因为任期号连续),但不知为何,它们还没有复制自己的日志到其他节点就崩溃了,系统分区了一段时间,S1、S2、S3轮流成为任期5,6,7(S3成为5,S1成为6,S2成为7)的领导者,但无法与S4,S5进行通信,执行日志清理,造成图中的局面。

图中唯一可以确定的是,日志索引1到3之间的日志是已提交的,因为他们已存在多数节点中,因此我们必须确保留下它们。而其他日志是未提交的,我们还没有将这些命令传递给状态机,也没有客户端会收到这些执行结果,所以无论保留或丢弃都无关紧要。
=>重要的是 状态机应用的一条日志中的命令,确保其他状态机在同样的索引位置执行相同的命令。

Raft算法的安全性就是为了保证状态机复制执行相同的命令。安全性要求,如果某个日志条目在某个任期已被提交,那么这个日志必然出现在更大任期号的未来领导者的日志中。
这保证了状态机命令的安全性,意味着:第一,领导者不会覆盖日志已提交的条目(注意是已提交的条目);第二,只有领导者的日志条目才能提交,并且在应用到状态机之前,日志必须先被提交

因此选举过程中,需要进行如下内容的检查:
(1) 如果节点的日志中没有正确提交的日志,则需要避免其成为领导者。
(2) 如果领导者在日志复制到多数节点后就宕机了,则后续领导者必须延迟提交日志记录,直到这条记录是安全的——后续领导者的日志中也包含这条日志。
这一优化手段被称为延迟提交,延迟提交的前提是先选出最佳领导者。最佳领导者为任期号最大的,如果任期号相同,则为日志最多的。流程可以如下实现:
(1) 在候选者的RequestVote消息中包含自己日志中最后一条日志条目的索引和任期,记为lastIndex和lastTerm。
(2) 收到此投票请求的服务器V将比较谁的日志更完整,如果V.lastTerm < C.lastTerm,则投票给C,或者V.lastTerm == C.lastTerm && V.lastIndex< C.lastIndex ,则投票给C,否则拒绝投票。

Raft算法的选举限制保证选举出的领导者的日志任期最新,长度也最完整,可以避免领导者追赶其他节点的日志。Raft中领导者是权威的。

选举限制举例

第一种情况:领导者决定提交日志

请添加图片描述
任期为2的领导者S1的第四条日志被复制到服务器S3,且已超过半数服务器,该日志可以提交并且安全地应用到状态机。
这条记录是安全的,那么下一任领导者必须包含这条记录,如果发生下次选举,则S4、S5不可能获得选举:日志不够新,任期太旧。

第二种情况:领导者试图提交之前任期的日志

请添加图片描述
如图所示,任期为2的日志条目一开始只写在服务器S1和S2两个节点上,由于网络分区,S1宕机,S5不知道这些记录,在选举过程中,S5赢得选举(获得S3,S4,S5的选票),领导者S5创建自己任期的3条记录,还没来得及复制就宕机了。之后任期4的领导者S1被选出,S1试图与其他服务器的日志进行匹配,因此它复制了任期2的日志到S3.
虽然此时Index=3,Term=2的日志已经被复制到多个节点上,但这条日志是不安全的。因为有可能领导者S1在提交后立即宕机,S5发起选举,赢得选举。一但S5成为领导者,它将复制Index=3到Index=5的日志到其它服务器,会覆盖S2、S3的Index=3,Term=2的日志——这不符合安全性中已提交日志不得被更改的条件。
因此Raft需要延迟提交。

延迟提交

Raft要求领导者想要提交一条日志,必须满足:
(1) 日志必须存储在超过半数的节点上
(2) 领导者必须看到超过半数的节点上还存储着至少一条自己任期内的日志。请添加图片描述
通过以上的限制,之前的情况下,Index=3,Term=2的日志在S1重新赢得选举后还不能提交,直到Index=4,Term=4的日志被存储在超过半数节点上,才会被提交,此时Index=3,Index=4的日志都被认为是已提交的。
之后,S1宕机,S5也不能赢得选举,因为S5的Term=3 <S2、S3的Term。
但这个方案并没有完全解决Raft的安全性。通过论文中的安全性讨论来说明。

论文中的Safety

在这里插入图片描述
论文中以这张图描述,为了更清晰,用以下图来说明。
请添加图片描述
如果领导者可以提交之前任期的日志,那么流程如下:
(1) S1为任期2的领导者,并将日志复制到S2
(2) 领导者S1宕机,S5获得S3,S4,S5的选票成为领导者,向自己写一条Index=2,Term=3的日志
(3) 领导者S5刚写完就宕机了,S1重新当选领导者,当前任期currentTerm=4。此时客户端没有新的请求过来,领导者S1将Index=2,Term=2的日志复制到S3,达成多数派,将日志提交。此时客户端发出请求,写入一条Index=3,Term=4的日志,领导者S1又发生故障了。
(4) 这时服务器S5可以获得S2、S3、S4、S5的选票成为领导者,将Index=2,Term=3的日志复制到其它节点并提交,此时Index=2的日志被提交了2次。这对于状态机来讲是不允许的。
(5)实际应该是d2所示状态,领导者只能提交自己的任期的日志,从而间接提交之前的日志。

加上这个约束,处理流程为:
(1) (2)流程相同
(3) S1当选领导者后,将Index=2的日志复制到大多数,但只能提交自己任期的日志即Term=4的日志。之后将Index=3,Term=4的日志复制到大多数后,就能提交日志了,同时间接提交了Index=2,Term=2的日志。

上述(4)是理解问题的关键。
如果领导者S1只将任期为4的日志写入自己本地,然后就宕机了,那么服务器S5通过S2、S3、S4、S5的选票成功成为领导者,然后将索引为2,任期为3的日志复制到所有节点,现在Index=2的日志是没有提交过的,S5能够将Index=2,Term3的日志提交吗?
在这里插入图片描述
答案是不能。因为领导者S5选举成功后,其Term至少为5,而第二条信息的任期为3,我们在之前约束了领导者不能提交之前任期的日志,所以这条日志是不能提交的。只有后续的请求到来后,超过半数节点复制了任期为5的日志后,任期为3的日志才被间接提交。

为了解决没有新请求进来无法提交日志的问题,Raft引入一种no-op的空日志。no-op只有索引和任期号,命令信息为空,目的是保持领导者的权威。
具体流程是:领导者刚选举成功时,不管是否有客户端请求,立即向自己本地追加一条no-op空日志,并立即将no-op空日志复制到其他节点。no-op日志属于领导者的日志,多数派达成后立即提交,no-op空日志之前的任期未提交的日志也就全部间接提交了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值