写在前面
接触分布式已数月有余,从zk到dubbo到springcloud都只是停留在应用层,此系列文章将深入探讨分布式背后的实现算法,如何保证分布式下的容灾与数据一致性,由于笔者水平有限,只是以自己的理解记录分布式算法实现,严谨的推导过程仍需另寻其他神犇~
阅读前可参考博主的另一篇文章:带你通俗理解Paxos算法
一、宏观理解Raft算法- 了解过Paxos算法我们熟知:Basic-Paxos有许多问题,比如提案活锁,两次RPC最主要是角色过于复杂难以落地实现,所以引出了Multi-Paxos算法,简化了角色定义,Raft就是Multi-Poxos的具体实现算法之一
- Raft算法将问题划分为了三个子问题:Leader Election(领导者选举)、Log replication(日志复制)、Safety(安全恢复),关于每个状态的行为我们在后文中讲解
- Raft算法重新定义了角色:分为Leader(领导)、Follower(追随者)、Candidate(候选者),并且一个节点的角色是可以改变的,具体的角色变化我们后文讲到
具体流程结合动图网站理解更佳Raft动图演示
1.首先我们明白几个概念:
- 选举过程是由两个超时时间来控制的:election timeout:也就是说在election timeout内Follow没有收到Leader的心跳检测,就会成为Candidate,通常是150ms到300ms的随机值;heartbeat timeout:发送心跳检测的时间间隔
2.整个流程
- 集群初始没有Leader,各个节点最先经过election timeout的节点会成为Candidate候选者
- Candidate会立即开启一个选举任期,首先它会投自己一票,并发送投票请求给其他节点
- 接着每个Follow会响应投票,并且每个选举任期只能投一票,并且会重置election timeout,防止Leader还活着呢,Follow就像篡位
- 一旦Candidate获得了大多数Follow的投票就会立马变成Leader,如果没办法票数不能超过一半就无法选出Leader,会清空计时重新选Candidate
- 接着Leader为了维护自己的地位,每搁一个heartbeat timeout就会向Follow发送心跳检测重置Follow的election timeout,Leader一句话:你们不要 BB! 按我说的做,做完了向我汇报!"
- 这个选举任期直到Leader挂了,Follow没有在election timeout内收到心跳检测为止
3.接下来是异常流程
a).Leader任期结束了,怎么重新选举?
- 如果Follow没有在election timeout内收到心跳检测就会变成Candidate,然后立马发起新一任的选举投票,投票成功就会当选新的Leader
b).如果有两个Follow同时成为Candidate怎么办?
- 如果同时有两个Candidate在同一任期内进行选举,并且票数相同,那么此时所有节点所有节点开始重新计时变为Candidate,由于election timeout是随机数,所以一定会出现一个唯一的Candidate
当我们选出Leader后,所有的请求必须经过Leader,整个集群又是如何达成数据一致性的呢?也就是说我们一旦选出了Leader,我们需要将对Leader的修改同步复制到所有的Follow
具体流程如下:
- 记得我们前文提到的心跳检测么?对于数据的同步 *** 作就是追加在心跳包中一起发送给Follow
- 当Client发起一个请求比如set x = 5,首先这个请求会发给Leader,首先这条指令会加入到Leader的日志文件中,此时Leader并没有真正地修改数据
- 接着会把set x = 5请求加入到下次的心跳检测包中发给Follow,Follow会发送ACK给Leader并且把指令写到Log中并没有真正修改数据
- 当Leader收到全部数量的Follow,首先真正修改数据,然后返回给客户端请求结果,接着在下次心跳包中告诉Follow去真正地修改数据,Follow收到后进行数据修改
- 我们不难看到,也是两阶段提交协议,两阶段提交协议是保证一致性地常用手段
我们假设一种场景,原本正常地集群出现网络分区后怎么办?
- 此时可以看到虚线上方地三个Follow无法再接受到Leader的心跳检测了,所以三个Follow会开始再election timeout到时后成为Candidate重新选举Leader,并且两个Leader的任期是不同的,最终会变成下图状态
- 同时由于共5个节点,下半分区Leader在接收Follow反馈时,无法得到大多数节点反馈,所以不能此时指令只能写入到log中,无法真正写入,也就是无法执行二阶段提交的第二阶段执行
- 当分区恢复后,任期计数大的Leader会成为新集群的Leader,分区下方的节点会回滚还未提交的事务,并且同步新Leader的日志达成集群的一致性
- 所以即使强如Raft算法,再出现网络分区后,也会出现数据不一致地情况,比如客户端是无法感知出现网络分区地,我们向产生分区前地Leader发送请求,那么请求只能保证上图中下半分区一致,和上半分区也会出现不一致地情况,但一旦网络分区消除,整个集群又会达成一致性的场景
Raft算法和ZAB协议都是基于Paxos算法,ZAB协议会在后序系列文章中逐渐展开描述,觉得不错点个赞就是对博主最大的鼓励,水平有限难免有理解不到位的地方,欢迎评论区讨论~
理论终归是理论,博主近期尝试将Raft算法落地实战,敬请期待~
参考
- B站分布式算法视频:地址
- Raft动图网址:Raft动图演示
- 极客专栏:分布式协议与算法实战
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)