从PAXOS进化到ZAB协议

本贴最后更新于 3075 天前,其中的信息可能已经斗转星移

从PAXOS进化到ZAB协议

没错,看了 从PAXOS到ZOOKEEPER这本书,然后写一篇博文总结下 PAXOS吧。

一、PAXOS简介

之前一篇文章就对PAXOS做了简单的介绍

PAXOS解决的问题是 在分布式环境中确定某一个 “不可变变量X” 的值。

PAXOS有以下特性:

  • 只要过半数Acceptor存活,那么就能正常的进行 X 值议案选举,并选定X的值
  • 只要有Leaner存活,那么外部要么拿不到对应的值,要么拿到的值就是最终确定的
  • 需要被确定的某个值一旦被确定了,那么就不会再变更
  • 只要有一个proposer存活,那么就能持续的给Acceptor提出议案

具体的PAXOS算法过程请参考我的另外一篇文章 说人话的PAXOS算法简介

二、PAXOS算法的缺点

我们可以从PAXOS算法的过程发现,PAXOS算法有以下性能缺点

  • 多个Proposer同时提议案会降低议案的抉择速度
  • PAXOS算法单个实例只能决定一个X的值,但通常运用场景中,我们需要确定多个X的值
  • Learner越多,Acceptor和Learner之间的通讯消耗会成指数级别上升

下面,我们来一一解决PAXOS的这些缺点

三、解决多Propser的问题

多proposer存在的意义是避免单点故障,实际上,正常时刻,我们同一时间只需要一个proposer正常运作,其他proposer standby。因此,解决方案很简单,设计一个主备算法即可。

选定主proposer的一个算法可以如下:

  • 任意一个proposer觉得有必要发起主proposer选举时,就可以发起proposer选举
  • 发起时,同时把自己的投票的结果 及 自己当前事件对应的逻辑时间 告诉所有proposer
  • 当某个proposer获得过半的选票时,该proposer就成为了主proposer
  • proposer投票的依据是 每个proposer的当前逻辑时间。
  • 拥有最大逻辑时间的proposer将会被选举为主proposer

选定了主proposer后,议案的提议就全都交给了主proposer提高效率,减少了议案选定过程中的通讯。

选定了主proposer后,当前处于主proposer就可以跳过 prepare-promise这个步骤,直接提交议案。因为正常运行时,只有他会提出议案,因此,该proposer的 逻辑时钟一直都是最新的。若这个proposer失去了主proposer的地位时,他直接提出议案时,会收到acceptor的reject反馈,这意 味着有其他机器竞争主proposer,要重新进行选举

四、解决多PAXOS实例的需求

正常的运用场景中,我们需要确定多个未知议案的值。因此需要多个PAXOS算法实例一起运作

我们回顾一下,单个paxos算法 提出及选定一个议案的过程是

收集accptor收到的议案信息,然后由proposer根据整合的议案信息 发送一个带有逻辑时间编号的议案到各个acceptor中,等待接收过半数acceptor的选定结果。

那有多个议案的时候,我们有什么东西可以重用的呢? 实际上,proposer,acceptor以及逻辑时间等信息都是可以重用的,因为单个paxos算法对于逻辑时间的要求仅仅是递增而已,多个 paoxs实例的值可以一次过由proposer提交给acceptor投票,并有acceptor选择全部通过,或者全部失败。

若对于多个PAXOS算法实例有 顺序编号等要求的话,编号可作为议案X的值的一部分,一起予以选定。编号的值的选取可参考逻辑时间的设定

五、解决LEANER个数上升,通讯次数指数上升的问题

其实这个问题很好解决,实际上leaner之间获得最终结果的时间也不是一致的。因此 leaner的个数设置2-3个即可,这样就解决了单点故障。如果有更多的进程想要知道程序选定的结果的话,那么,由这两个leaner主动推送结果,或者由其他的进程主动过来向leaner查询即可。这样,就解决了通讯次数指数级别上升的问题。

六、PAXOS中逻辑时钟的意义

PAXOS算法中,每个议案都需要附上议案对应的编号(或者说是逻辑时钟的时间),这个时间代表的意义是:这个议案的提出已经综合了对应议案时间及之前的所有的情况,ACCEPTOR你就看看这个议案是否还没过期适用于当前的情况把~

在原始的PAXOS算法中,每个proposer在给出propose的时候都不清楚自己掌握的情况 是否最新的,因此给出这个逻辑时间给acceptor来判断是必不可少的。但假设我们按照之前的做法,给paxos算法的proposer加入了主备,一 个proposer一直都是主proposer,只能由它提出建议的话,那么acceptor就可以默认相信该proposer的议案,而不用管议案的编 号,因为该proposer总掌握了当前最新的情况。

七、引入主PROPOSER周期

但当主proposer挂掉了,我们需要选举另外一个掌握了所有情况的proposer来担任主 proposer。那要如何获得一个掌握了所有情况的proposer呢?很简单,向过半数的acceptor获取统计运行情况即可。当获取完毕,这个 proposer就掌握所有情况,可以向accptor提出合法的建议了

但这个时候,原来的主proposer又复活了怎么办?他之前只是由于网络分区等问题失联了而已。现 在又给acceptor发propose了!其实...这种时候,我们可以参考之前的逻辑时钟的设定,搞一个第几任主proposer的编码。如某 proposer进程第一次当选时,其编号为1,下一个进程当选时的那次,编号则为2。这样,当acceptor正处于编号为2的主进程周期时,收到了编 号为1的propose时要予以拒绝。这里的主进程编号跟之前的逻辑时钟的编号的意义也是一样的,如 主进程编码为1的议案表示的是,本议案已结合了 主进程阶段1及之前所有阶段的情况,给出了这个建议,acceptor你就看看要不要接受把。

八、主PAXOS周期+多PAXOS算法实例

以上这个主PROPOSER周期的改进,可以跟多PAXOS实例结合使用。可以每个主 proposer周期内依次运行的PAXOS算法实例进行编号,主PROPOSER需要提交某些PROPOSE的时候,忽略prepare- promise步骤,直接将 议案值 及 PROPOSER周期 及 PAXOS实例编号发给各个ACCEPTOR 并收到过半数回应即可认为议案被选定。

九、ZAB协议与PAXOS

了解过ZAB协议看过上述PAXOS优化之后,应该能察觉到,上述经过优化的协议与ZAB几乎一致。

  • ZAB没有PROPOSER,ACCEPTOR,LEANER的区别,但实际上,ZAB只是将PROPOSER,ACCEPTOR,LEANER合并成同一个进程。
  • ZAB存在一个LEADER,对应上述PAXOS优化方案的主PROPOSER
  • ZAB协议分为 消息广播 及 崩溃恢复两部分。
    • 消息广播部分对应省略了PREPARE-PROMISE步骤的PAXOS算法
    • 崩溃恢复对应于主PROPOSER选举(当然,还有些细微差别)
  • ZXID对应于 主周期及PAXOS算法实例编号组合

十、总结

嗯,就这样。帮助巩固了PAXOS和ZAB

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...