zookeeper⼊门系列-理论基础-zab协议
上⼀章讨论了paxos算法,把paxos推到⼀个很⾼的位置。但是,paxos有没有什么问题呢?实际上,paxos还是有其⾃⾝的缺点的:
1. 活锁问题。在ba-paxos算法中,不存在leader这样的⾓⾊,于是存在这样⼀种情况,即P1提交了⼀华清池
个proposal n1并且通过了prepare阶段;此时P2提交了⼀个proposal n2(n2>n1)并且也通过了prepare阶段;P1在commit时因为已经通过了n2⽽被拒绝;于是P1继续提交⼀个葡萄干孕妇能吃吗
proposal n3并且通过prepare阶段;巧的是此时P2开始commit了,由于n2<n3再次被拒绝……如此循环往复。这种情况被称为活锁。即整个系统都没死,但由于互相请求资源⽽被互相锁死。为了不发⽣活锁的情况,最简单的⽅式当然是缩减propor到⼀个,这样就不会发⽣互相请求锁死的情况,也即退化。销售合同书
事实上很多后来的⼯业级协议,都是paxos协议的退化或者变种。
2. 复杂度问题。ba-paxos协议中还存在这样那样的问题,于是各种变种paxos出现了,⽐如为了解决活锁问题,出现了multi-paxos;为了解决通信次数较多的问题,出现了fast-paxos;为了尽量减少冲突,出现了epaxos。可以看到,⼯业级实现需要考虑更多的⽅⾯,诸如性能,异常等等。这也是为啥许多分布式的⼀致性框架并⾮真正基于paxos来实现的原因。
3. 全序问题。对于paxos算法来说,不能保证两次提兔和什么生肖相冲
交最终的顺序,⽽zookeeper需要做到这点,可以参
考⽂献1。
For high-performance, i浴缸英文
t is important t开学了手抄报内容
hat
ZooKeeper can handle multiple outstanding state changes requested by the client and
that a prefix of operations submitted concurrently are committed according to FIFO
order.
基于以上这些原因,zookeeper并没有⽤paxos作为⾃⼰实现的协议,取⽽代之采⽤了⼀种称为zab的协议,全称是zookeeper atomic broadcast。下⾯简单介绍⼀下zab协议。
上⾯说过了,paxos存在活锁问题,为了解决活锁问题,zab引⼊了leader,但是单leader就是⾚裸裸的单点问题,如何解决这个单点呢?
paxos采⽤的⽅法是leader选举(没有采⽤主备,因为主备过于固定,不够分布式)。leader选举就必然出现状态不⼀致的情况,于是就有着同步这样的过程。
zab协议分为4个阶段,即阶段0为leader选举,阶段1为发现,阶段2为同步,阶段3为⼴播。⽽实际实现时将发现及同步阶段合并为⼀个恢复阶段。
0. leader选举阶段。当集群中没有leader或者其他⼈感受不到leader时会进⼊这⼀阶段,这⼀阶段的主要⽬的三年级下册班主任工作计划
是选出zxid最⼤的节点作为准leader。
1. recovery阶段。本阶段的主要⽬的是根据准leader的情况将数据同步到其他节点。同步完成后准leader变为leader。
2. broadcast阶段。本阶段的主牛肉炒辣椒的做法
要⽬的是leader收到请求,并将请求转为proposal,其他节点根据协议进⾏批准或通过。broadcast阶段事实上就是⼀个两阶段提交的简化版。其所有过程都跟两阶段提交⼀致,唯⼀不⼀致的是不能做事务的回滚。
⼴播的过程实际上类似于⼆阶段提交,但是如果实现完整的两阶段提交,那就解决了⼀致性问题,没必要发明新协议了,所以zab实际上抛弃了两阶段提交的事务回滚,于是⼀台follower只能回复ACK或者⼲脆就不回复了,leader只要收到过半的机器回复即通过proposal。但是这样的设计就存在很多问题,⽐如如果⼀个follower因为⽹络问题从头到尾⼀直没收到过leader的proposal,后续的询问刚好落到这台follower上该如何处理?⽐如leader第⼀阶段收到了所有follower的ACK后提交,然后通知其他follower提交,这时⾃⼰挂了该如何处理?于是诞⽣了崩溃恢复阶段,旨在对各种不⼀致情况做出恢复和处理。
对于选举和恢复阶段。zab算法需要确保两件事。
1. 已经处理过的proposal不能被丢弃。
发⽣场景:leader发送了proposal,follower1和follower2回复了ACK给leader,leader向所有follower发送commit请求并commit⾃⾝,此时leader挂了。leader已经提交,但是follower尚未提交,这会存在不⼀致的情况。
确保⽅式:
a. 重新选举leader时只挑选zxid最⼤的follower。因为⾄少半数的follower曾今回复ACK,意味着重新选举时zxid最⼤的follower应该是当初回复ACK但尚未提交的其中⼀台。
b. 该follower即准leader,将⾃⾝收到prepare但尚未提交的proposal提交
c. 在选举阶段准leader已经能拿到其余follower的所有事务集合,于是准leader根据各个follower的事务执⾏情况,分别建⽴队列,先发送prepare请求,再发送commit请求,让所有follower都同步到与leader⼀样的状态。
通过以上⽅式,能够确保提交过的proposal不会出现丢弃的情况。
2. 已经丢弃的proposal不能被重复处理。
发⽣场景:leader收到请求,包装为proposal,此时⽹络挂了或者leader挂了导致其他follower没收到请求,此时进⼊崩溃恢复阶段,此时其他follower选主并成功之后这个挂了 的leader以follower的⾝份加⼊,此时它有⼀个多余的proposal,与其他节点不⼀致。
确保⽅式:
通过zxid的⼤⼩能够直接确定。zxid的编码⽅式为⾼32位为epoch(即纪元,可以理解为代),低32位为每个proposal顺序递增的数字。每次变换⼀个leader,则epoch加⼀,可以理解为改朝换代了,这样,新朝代的zxid必然⽐旧朝代的zxid⼤,新代的leader可以要求将旧朝代的proposal清除。
可以考灯塔歌词
虑⼀下,如果lea积极分子推优
der在崩溃恢复阶段就满⾎复活了,此时集群的情况是什么样的。