当前位置: 首页 > 科技观察

分布式共识算法:它可能比你想象的要复杂

时间:2023-03-20 11:02:01 科技观察

1。分布式系统的难点张胖子遇到了一个问题。他们公司有一台服务器,里面存放着有价值的数据。为了不让它挂掉,领导比尔让张大胖想办法备份数据。张胖子使出自己的抽象能力,脑子里浮现出这样的画面。单机可以成为节点:为了提高可用性,可以增加几台机器,通过局域网连接起来,形成一个分布式系统:如果每个节点上都存一份数据,是不是就可以高枕无忧了?但是张胖子很快发现,这不是一件容易的事。比如每个节点保存一个余额为100元的账户。去了30元。现在余额是多少?为了保持一致性,节点A必须向B和C发送“余额加20”的消息,节点B必须向A和C发送“余额减去30”的消息。如果网络出现问题,消息如果没有发送到其他节点,或者某个节点干脆坏了,数据很可能不一致。如果用户继续在这个不一致的系统上操作,混乱很快就会接踵而至。2.谁来做老板?张胖子想了半天,觉得不能这么乱操作,得给这三个节点找个“老大”。所有的操作都是通过“老大”进行的,然后让老大把消息发给各个“小弟”。但是谁会是老大呢?还有,boss死了怎么办?可以手动调整。比如A节点挂了,手动让B节点做“老大”,让C节点做“小弟”。但是这个有点麻烦,能自动实现吗?这个问题很有意思,张胖子看得入了迷,继续深思:建立一个竞选机制,让他们竞争上岗。最初,每个节点都是一个候选人,可以邀请其他节点为自己投票。如果获得半数以上的选票,他们就可以成为“老大”。为了防止大家同时发起投票邀请,可以给每个节点分配一个随机的“选举超时时间”(electiontimeout)。一般来说,这是一个等待时间。在此期间,节点必须耐心等待。这段时间可以争岗,争当老大。每个节点都有一个定时器,从0开始计时,谁等到时间到了,谁就最先发起竞选,调用其他节点,让他们投票让自己成为leader。比如节点A等待170ms,节点B等待200ms,节点C等待250ms。由于节点A等待时间最短,它会先走,它先增加自己的任期(Term),它是一个整数,初值为0,然后给自己投票,然后调用节点B和节点C,询问他们投票赞成。节点B和节点C都收到了投票请求。如果他们还没有发起选举投票(等待时间还没有结束),他们就必须同意节点A成为领导者。也就是说,开始新一轮的等待。节点A知道另外两个节点同意了,票数变成3,也就是一半的票数,所以他知道自己可以当leader了。节点A成为老大后,开始定时向节点B、C发送消息,B、C收到消息后也进行响应,维持心跳。B和C每次收到心跳报文,都要重新设置定时器,重新从0开始计数。这时,B节点和C节点就成了“小兄弟”。如果A节点不幸挂掉,B节点和C节点在自己的等待时间内无法收到心跳报文,两者又会重新竞争上岗。上图中,节点C率先发起选举投票。B节点慢了一步,勉强同意支持C节点,C节点获得过半支持,成为“老大”,B节点成为“小弟”。(可能有人会想:节点B和节点C同时发起选举投票,每个节点的投票数都是1,无法通过一半的选票。怎么处理?很简单,发起即可另一轮选举投票为了防止B和C同时发起选举投票,从而陷入***循环,必须重新设置一个随机等待时间。)超过一半的选票非常重要,张大发认为,只有这样才能保证“boss”节点的唯一性。对于每一个节点,处理流程其实很简单:3.数据复制张大胖折腾了半天,终于确定了如何在分布式系统中自动选出“boss”节点。接下来就是想办法把发给“老大”的数据复制到“小弟”的节点上。如何处理?因为是分布式的,只有大多数节点成功保存数据才算成功。所以“老大”节点必须承担起协调的责任。张胖子想到了一个复制日志的方法:每个节点都有一个日志队列。在真正提交数据之前,先将数据追加到日志队列中,然后复制给一个“小弟”。1.客户端向节点A(“老板”)发送数据。节点A首先在日志中记录数据,即此时处于“未提交状态”。2、在接下来的心跳报文中,将数据发送给各个“小弟”。3、每个“小弟”也把数据记录在日志中(也是未提交状态),然后向“老大”报告自己记录了日志。4.如果节点A收到超过一半的响应,节点A提交数据并通知客户端数据保存成功。5.在下一个心跳报文中,节点A通知各个“小弟”数据已经提交。每个“小弟”也提交了自己的数据。如果有“小弟”不幸挂机,“老大”会继续尝试联系。一旦再次开始工作,就需要从“老大”那里复制数据,与“老大”保持一致。4.RAFT张大庞对初步设计方案比较满意,将方案交给领导Bill审核。比尔看完后笑着说:“你现在其实是在折腾一个共识算法,说白了就是让一群机器作为一个整体来工作,哪怕其中一部分失败了。”“对对对不对,领导总结的真准确。”张胖子恭维他。“不过,”比尔话锋一转,“你设计的日志复制还是有很多漏洞的,我觉得你的设计有5个步骤,万一‘老大’节点A在这5个步骤挂掉了怎么办??数据不一致?”“这……”张胖子还真是没有细想。他暗自后悔自己只是低着头拉车,忘了抬头看路,忽略了分布式环境中复杂的问题。“不过你做的很好,”领导立即鼓励道,“你设计的系统其实和RAFT算法非常相似。““筏?”“是的,RAFT是一种分布式共识算法。相对于复杂难懂的Paxos,RAFT在可理解性和可实现性上有了很大的提升。你这里的“老大”,RAFT算法叫Leader,“小弟”叫Follower,但是他们对日志复制,如何保证数据一致性都有很详细的规定。张胖子一听有现成的算法,顿时乐了起来:“太好了,分布式问题别人已经解决了,我来实现一下。”》【本文为专栏作家“刘欣”原创稿件,转载请通过作者微信获得授权公众号coderising】点此查看该作者更多好文