理解Raft协议
Ye_yang 人气:01.Paxos算法存在的问题
-
难以理解
Paxos算法是如何工作的?
Paxos算法每个阶段的意图是什么?
很难产生直观的感受。
-
难以实现并应用于现实中的系统
人们在实现Paxos算法时,发现很多实现上的难题,最终开发出和Paxos算法不一样的结构。
2.Raft算法
Raft协议由Diego Ongaro和John Ousterhout(斯坦福大学)共同于2014年设计。
2.1 复制状态机
每一个服务器存储着一个日志序列。每一个服务器按照顺序应用每条日志(或称之为执行指令),并应用到状态机中。
保证了日志序列相同,那么,在应用每条日志(或称之为执行每个指令)时,每台服务器的状态机状态都是一致的。
保证日志序列相同就是一致性算法的工作。
2.2. Raft算法
Raft选举出一个Leader,通过Leader管理日志复制来实现一致性。
Leader从客户端接收日志条目,将日志条目复制到其他服务器上。当确保安全性的时候,告诉其他的服务器应用日志条目到他们的状态机上。
为了可理解性,Raft对通过问题分解,将算法分为了几个独立的部分
-
Leader选举
-
日志复制
-
安全性问题
2.2.1 安全性问题
特性 |
解释 |
---|---|
选举安全原则 |
对于一个给定的任期号,最多只会有一个领导人被选举出来 |
领导人只附加原则 |
领导人绝对不会删除或者覆盖自己的日志,只会增加 |
日志匹配原则 |
如果两个日志在相同的索引位置的日志条目的任期号相同,那么我们就认为这个日志从头到这个索引位置之间全部完全相同 |
领导人完全原则 |
如果某个日志条目在某个任期号中已经被提交,那么这个条目必然出现在更大任期号的所有领导人中 |
状态机安全原则 |
如果一个领导人已经在给定的索引值位置的日志条目应用到状态机中,那么其他任何的服务器在这个索引位置不会提交一个不同的日志 |
2.2.2 Leader选举
一个Raft集群包含若干个服务器节点,通常是5个,允许整个系统容忍2个节点的失效。
在任何时刻,每一个服务期节点都处于以下3种状态之一:
-
Leader:处理所有的客户端请求(如果客户端将请求发给了Follower,Follower会把请求重定向给Leader)
-
Follower:不会发送任何请求,只会简单地响应来自Leader或Candidate的请求
-
Candidate:用于选举产生新的领导人
Term——任期
1)每个任期最多只能有一个领导人Leader
2)有时候任期内可能没有领导人(因选举失败)
3)每台机器上维持着当前的任期号。
会在每次RPC通信时会将自己的任期号进行传递(可用于识别过时的信息)
如果RPC收到任期号大的值,变为follower。
如果RPC收到过期的任期号,返回错误信息。
1)每个机器只能投一次票(含投给自己)
2)获得多数选票的成为leader
问题:
如果选举过程中,一直没有一个Candidate获得大多数选票,将一直进行重复选举。
如何保证会有一个Candidate会获取到大多数选票成为Leader?
Raft的解决方法:随机超时时间,保证只有一个follewer超时,变成Candidate,并(在其他follower超时前)发送投票请求,得到大多数的选票,从而成为leader。
2.2.3日志复制
客户端发送命令给Leader。
Leader把日志条目加到自己的日志里。
Leader发送AppendEntries RPC请求给所有的follower。
日志一致性检查
AppendEntries RPC里包含着prevLogIndex,prevLogTerm。
Follower接收到后,会检查相应的日志条目是否匹配上
1)如果匹配上了(Example#1),将收到的日志条目添加到自己的日志里。
(根据【日志匹配原则】,表示follower和leader的prevLogIndex以前的所有日志条目是安全相同的)
2)如果没有匹配上(Example#2),follower将拒绝此次请求,Leader将index调小,不断进行重试,直到匹配上。
(Example#3)follower会将后面的日志条目全部删除,再将leader的日志条目添加上。
日志提交
(日志提交:指将日志条目应用到状态机中)
一旦新的日志条目变成【已经复制到大多数follower机器上】的了。
(PS:关于上面所讲的“大多数follower机器”个数?
问题:可以这么理解吗?
满足【“大多数follower机器”个数 + leader > 集群中机器个数的一半】就可以。
比如,集群中机器个数为5,“大多数follower机器”个数为2就可以了。
答案:
不可以,因为如果leader宕机不重启,无法保证仍旧为大多数。
)
-
Leader在状态机里提交自己日志条目,然后返回结果给客户端
-
Leader下次发送AppendEntries RPC时,告知follower已经提交的日志条目信息(lastIndex)
-
foller收到RPC后,提交到自己的状态机里
在Raft运行过程中,可能的各个机器日志条目状态如下。
问题:
领导人S1宕机了,重新进行选举,是每台机器都可以被选举成为新leader吗?
如果S4被选举成term 4的leader,会发生什么问题?
答案:
当S4发送AppendEntries RPC请求给所有的follower时,
在进行日志一致性检查时,会将follower已经提交到状态机中的日志条目给删除掉!!从而违反了状态机安全原则。
如何保证选举出的新leader包含所有已提交的日志条目?
选举规则的限制:Candidate发送的RequestVote RPC中含有lastIndex,lastTerm。
当机器收到后,如果Candidate的日志不如自己的新,将拒绝投票给它。
日志的新旧的比较:通过比较两份日志中最后一条日志条目的索引值和任期号定义谁的日志比较新。
-
如果两份日志最后的条目的任期号不同,那么任期号大的日志更加新。
-
如果两份日志最后的条目任期号相同,那么日志比较长的那个就更加新。
S1:选票(S1,S2,S3,S4,S5)可获得多数选票
S2:选票(S2,S4)
S3:选票(S1,S2,S3,S4,S5)可获得多数选票
S4:选票(S4)
S5:选票(S2,S4,S5)可获得多数选票
因此,S1, S3, S5可被选举为新的leader,S2,S4则不行。
思考:为何通过这种方式可以保证新选举的leader一定拥有已commit的日志条目?
答案:
leader在当日志条目【已经复制到大多数follower机器上】时,才会提交日志条目。
假设已经含有已提交日志条目的机器(可能含上一次的leader)组成的集合为Set。
根据以上选举规则的限制,可知新leader一定在Set中。
参考资料
[1] https://raft.github.io/raft.pdf Raft论文原文
[2] https://github.com/maemual/raft-zh_cn/blob/master/raft-zh_cn.md Raft论文翻译
[4] https://raft.github.io/ Raft官网
[5] http://thesecretlivesofdata.com/raft/ Raft算法可视化
[6] https://raft.github.io/slides/uiuc2016.pdf
https://www.youtube.com/watch?v=vYp4LYbnnW8&feature=youtu.be
Raft论文作者PPT讲稿及视频
加载全部内容