前言
上文以通俗的方式介绍了PAXOS,但 PAXOS 更偏向于理论模型,许多实现层面的细节都被一笔带过,而 Raft 的提出,正是为了让一致性协议更容易工程化落地
Leader
其实PAXOS本身无主的方式就有点反人类,现实中再平等的团体,也都需要一个leader的角色,因为真的要人人可提案,各种冲突太乱会导致办事效率太低了(PAXOS复杂的两阶段),而只要在选主的过程中实现人人可竞选就算是公平了
一般只要leader不出问题,就不会再次重新选主,所有提案都从主节点作为唯一的决策者,避免了复杂的冲突场景
PAXOS的论文最后提出的落地方案(后来被称为MULTI-PAXOS)就提出了选主的思路,但是整个描述还是主抓理论,所以才有后来的raft协议,看一下raft协议的自我定位:

主打的就是一个可理解,可落地。。。且raft还贴心的做了一个raft动态展示页面,理解起来非常爽
接下来依然延续上一文的故事,一个村子有了村长,所有的事都村长统一决策,其他人跟着干就可以了

选主
还是这个故事,假设现在村民意识到了选村长的重要性,准备选村长,但是还是那个问题,每个村民的行踪不固定,任何人随时都有可能失联
这就导致竞选村长这个事可能不是一次性的,没有村长需要选,有了失联的也要选,那此时就定义一个规则覆盖这个两个场景,村民只要一段时间内联系不上村长,就视为村长失联,重新竞选新村长(没有和失联都联系不上)
规定每个村民必须定时和村长通讯比如1小时一次,定一个时间比如3小时无法联系上村长,那这个村民就可以出来竞选新村长

在村长职位空缺的时候又回到了全民平等的场景,就不可避免的会出现冲突,回到了PAXOS的场景
可以尽量避免出现这种冲突,比如让每个村民开始计算时间的起点不一致,或者等待时间略微不一致,尽量避免出现多个村民同时出来选村长的情况
冲突
但是不管怎么设计,都只能减少但无法绝对避免多个村民都同时出来选村长的情况,所以这里又回到了PAXOS中的那个场景,如果有多人同时竞选,又会出现哪个候选人都无法过半的核心问题
PAXOS的思路解决非常直接,回顾一下:一人投一票 -> 导致可能选不出 -> 一人投多票 -> 导致选出多个 -> 保证多个选出提案相同值 -> 终
相比于PAXOS的复杂解决方案,zaft的解决方案更为简单,一人每一轮只能投一票,那选不出来怎么办?非常简单,再来一轮
所以重点是ZAFT引入了选举的轮次,初始的时候大家都是0,每次有人发起选举的时候+1,同时投票的人发现轮次已经升了,发现已经开始了新一轮选举,就更新自己的轮次
这样就非常简单了,假如现在是轮次是5,村长失联了,有两个人发现固定时间联系不上村长,几乎同时把自己当做候选人开启第6轮选举,如果两人各得了一半的票,那这一轮选举就无法选举出村长,但所有村民还继续遵守着固定时间联系不上村长(实际已经竞选上的)就开始把自己变成候选人发起选举的规则,甚至候选人也继续坚守这个规则,所以不需要多久就会触发下一轮选举,由于多人同时参选本身就是小概率事件,所以多轮几次就一定能选出村长

一致
解决了村长选举的这个大问题,其他的问题一下就变简单了,什么决策都让村长决定,其他村民全跟着村长,一致性就非常好保证了,因为所有事只有村长一个人会提案
比如现在有个事,决定王寡妇的归属问题,村长说给谁就给谁,因为没有人有其他意见
落实
但真的就让村长说了就算了么,也不完全是,虽然只有村长有提案权,但一个提案也得确保多数村民得知后才能算落实,为什么这么做呢?
还是那个问题:任何人可能会失联,村长如果顶下来某个决策,但没告知村民,如果村长失联了,新选上得村长完全不知道这个决策,这个决策就丢失了。这是绝对不能接受的

所以村长再定决策前,一定要先把提案告知村民,村民知道后才能算落实,但保证每次都全村民都得知是不现实的,因为任何人可能会失联,所以这里依然是需要半数以上的村民得知,提案才算被落实
比如村长提案:“王寡妇归属光棍刘”,要提前把这个信息通知村民,当半数以上村民说我知道了,并记录了下来,此时提案落实,村长还需要再把落实的消息通知给村民,让村民知道这个提案实际生效了
半数以上的规则就有可能导致有的村民没有最新消息,但村民会把每一次提案和落实记录下来,这样就知道谁的数据新,而数据旧的村民想竞选村长是竞选不上的(村民不会给数据比自己旧的人投票篇,因此旧数据的人到达不了半数选票),所以即使村长失联,新选上的村长还是有最新数据
有一个极端情况就是村长已经把某提案同步给半数以上村民了,此时这个提案就落实了,但是还没来及的通知村民这条消息落实,村长就挂掉了,此时新选上的村长一定知道这个提案,但不知道这个提案落实了,他会重新开始通知落实这个提案,保证这种极端情况也不会丢信息
脑裂
再一个极端情况,假如现在一共就五个村民,其中村长和一个村民在村东头,其他三个村民在村西头,有一天突然发大水,导致村东头和村西头彻底失联
此时村东头的村长一直还是村长身份,另一个村民也能联系上村长所以不会有任何异议
而村西头由于三个人都联系不上村长,于是开始重新选举,由于有三个人能达到半数以上的要求,就选出一个新村长

此时一个村子同时出现了两个村长,也是技术领域常说的脑裂
这种情况出现也不会导致整个村子决策体系崩坏,因为村东头虽然村长依然存在,但已经无法决策了,因为他的任何决策都无法得到半数村民响应
而村西头的新村长正常情况下可以正常提案并可以落实,因为他们三人占多数
当慢慢河水褪去,两边村民重新开始取得联系时,村东头的村长和另一个村民会发现已经有一个新一轮选举的村长了,他们会妥协放弃原村长的身份,并把之前无法落实的提案作废,重新同步西侧村民的信息
最后
相比于PAXOS,ZAFT极其好理解也好工程化实现,使用RAFT的框架也非常多,如Kafka、Mongo、Consul等等
它解决一致性的思路就是选出一个主节点,只要保证主节点是唯一的,其他节点也能通过主节点来获取信息,从而很简单的就实现了一致性