Raft协议----‘’沧行‘’

Raft 是一种为了管理复制日志的一致性算法,该算法强依赖 Leader 节点的可用性来确保集群数据的一致性,即如果client向leader发起添加日志请求,如果leader回复client提交成功,那么该日志一定被过半数的server所提交,且是确定的不会被其他日志覆盖。

算法包含2类成员,server和client:

  • server:接受client的写日志请求,该类成员包含3种角色:
    • follower:跟随者,server集群首次启动时都是follower。
    • candidate:候选人,在follower的选举时间超时后会变为candidate。
    • leader:领导者,当server成为candidate后并发起选举投票请求收到过半数server的投票后会变为leader。
  • client:负责发起附加日志请求到server

算法包含两个过程:leader选举和日志复制:

1.leader选举

  • 该过程发生在server集群启动或leader宕机时,server最初都是follower,每个follower都维持一个选举超时时间,当选举超时时间到达后,follower会自动晋升为candidate,并发起投票请求给其他server,如果收到过半数server的投票同意响应,则晋升为leader,然后定时发送心跳请求给其他server(周期远小于选举超时时间),如果有了新的leader,那么其他server都变为follower,当收到leader的心跳请求后会重置自己的选举超时时间。
  • 每次选举都会产生一个新的递增的任期号。
  • 在server收到投票请求时,只有对方的最新日志比自己的日志新才会回复同意投票响应给对方,日志用任期号和日志索引来比较日志新旧,先比较任期号,再比较索引,任期号是日志从client发送到leader时该leader的任期号。
  • 在一次选举过程中,每个server最多只能投一次票。

2.日志复制

当选出一个leader后,便能够为client提供服务啦,即处理client的写日志请求,所有client的写请求最终都会发送到leader,leader收到client的写日志请求后,会执行如下:

  • 将日志写到本地文件;
  • 将日志复制给其他follower,其他follower收到日志后写到本地文件并响应leader写入成功;
  • 当leader收到follower的响应并且已经把日志复制到过半数的server节点(包括自己)后,commit该日志(把日志刷新到最终要保存的磁盘位置),并通知其他follower commit该日志。注意:只有该日志的任期号跟自己的任期号相同才能commit,上个任期号的日志在当前任期leader不能被直接commit,需要当前任期leader在commit当前任期日志时该日志索引之前的日志才会被自动commit

注意:当server节点宕机后节点数量不会发生变化,即该宕机的server还算做集群的一员,在选举和复制日志过程中还必须考虑其投票和复制日志响应。
日志处于两种状态才是安全的,如下:

  • 第一种状态是被commit的日志,该日志已经占据了日志索引位置,在以后才绝对不会被丢失和覆盖;
  • 第二种状态是该日志被复制到过半数的server,且该日志任期号与当前leader任期号相同;

第一种状态无需解释,针对第二种状态,即使该日志没有被commit,然后leader宕机了,那么没有该日志的server节点不可能选举成为leader,只有包含该日志的server才能被选举为leader,在选举成为leader后在复制日志给其他follower后并且也把自己任期的一条日志复制给过半数server后会commit自己任期的该条日志,那么上一个任期的日志也会被间接commit,注意,raft算法不会单纯的commit上一个任期的日志,只能在commit自己任期的日志时间接commit上一个任期日志。下面简单证明为什么leader把当前任期的日志复制到过半数的follower后相当于日志就是安全的了:

假设有5台server,包含1台leader4台follower,当有2台follower收到日志后该日志是安全的并且可以commit的,假设leader编号为1,任期号为1,收到日志的2台follower编号为2、3,没收到日志的3台follower编号为4、5,如下(表格第一行的1、2表示日志索引位置,日志内容<t,c>,t表示任期号,c表示日志内容):

 12
server 1(master)<1,x->1> 
server 2<1,x->1> 
server 3<1,x->1> 
server 4  
server 5  

如果这时server 1宕机了,但集群数量还是5(server节点宕机后也算做集群一员),那么只有比5/2+1=3台server(包括自己)的日志新才能选举为leader,所以只有follower 2、3才能成为leader,假设2成为了leader,任期号为2,它会将日志<1,x->1>复制给其他follower,如下:

 12
server 1<1,x->1> 
server 2(master)<1,x->1> 
server 3<1,x->1> 
server 4<1,x->1> 
server 5<1,x->1> 

然后server 2收到client的写日志请求,收到日志y->1,会把该日志复制给其他follower:

 12
server 1<1,x->1><2,y->1>
server 2(master)<1,x->1><2,y->1>
server 3<1,x->1><2,y->1>
server 4<1,x->1> 
server 5<1,x->1> 

如果server 2收到了过半数server的写日志成功响应,假设收到了server 1、3的响应,那么可以commit日志<2,y->1>了,如果通知其他follower commit成功那么之前的日志<1,x->1>也会被间接commit。

也就是说,过半数5/2+1=3,这个数量一定比未收到复制日志<1,x->1>的follower的总和2要大,所以不管有几台server宕机(当然不能超过5/2=2台节点宕机),未收到复制日志<1,x->1>的节点(server 4、5)都不会收到过半数server的投票而选举为leader(因为它一定没有比过半数server的日志新),只有包含那条复制到过半数server的日志<1,x->1>的server节点(server 1、2、3)才能选举成为leader,当其选举为leader后会把该日志<1,x->1>复制给其他follower,最终还是能成功commit该日志。由此可见,只有过半数5/2+1=3的server节点存活才能保证服务可用,如果server 1、2、3全宕机了那服务本身就不可用了,server 4、5不能提供服务不能接收日志写服务,也就不存在日志<1,x->1>被覆盖问题,在server 1、2、3重启之前永远不能提供服务。

下面解释下为什么leader在把上一个任期的日志复制到过半数server后该日志还是不安全的:

假设有5台server,1台leader,4台follower,leader编号为1,任期号位1,假设leader把上一个任期的日志复制给了follower 2,然后宕机了,如下(表格第一行的1、2表示日志索引位置,日志内容<t,c>,t表示任期号,c表示日志内容):

 12
server 1(master)<1,x->1> 
server 2<1,x->1> 
server 3  
server 4  
server 5  

然后server 5通过server 3、4选举成为leader,任期号为2,并把一条新日志复制给了server 4,然后又宕机了如下:

 12
server 1<1,x->1> 
server 2<1,x->1> 
server 3  
server 4<2,y->1> 
server 5(master)<2,y->1> 

然后server1通过server2、3选举成为leader,任期号为3,把日志<1,x->1>复制给了server 3,然后又宕机了,如下:

 12
server 1(master)<1,x->1> 
server 2<1,x->1> 
server 3<1,x->1> 
server 4<2,y->1> 
server 5<2,y->1> 

然后server 5又通过server 3、4选举成为leader,任期号为4,它会把日志<2,y->1>复制给其他follower,复制给server 1、2、3时会覆盖在索引位置为2的<1,x->1>日志,因为该日志没有被commit所以可以被覆盖,如下:

 12
server 1<2,y->1> 
server 2<2,y->1> 
server 3<2,y->1> 
server 4<2,y->1> 
server 5(master)<2,y->1> 

这种情况下虽然server 1在成为leader且任期号为3,把日志<1,x->1>复制到了过半数server,即server 1、2、3,该日志最后还是被server 5的<2,y->1>覆盖了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值