ZK原理

简介

ZooKeeper是用于分布式应用程序的分布式,开放源代码协调服务。它公开了一组简单的原语,分布式应用程序可以基于这些原语来实现用于同步,配置维护以及组和命名的更高级别的服务。
详见:https://zookeeper.apache.org/doc/current/zookeeperOver.html

可快速恢复leader

img
1,leader肯定会挂
2,服务不可用
3,不可靠的集群
4,事实,zk集群及其高可用
5,如果有一种方式可以快速的恢复出一个leader

zookeeper有2中运行状态
1,可用状态
2,不可用状态
3,不可用状态恢复到可用状态应该越快越好

特征&保障

img

paxos协议

是一个基于消息传递的一致性算法,Leslie Lamport在1990年提出,近几年被广泛应用于分布式计算中,Google的Chubby,Apache的Zookeeper都是基于它的理论来实现的,Paxos还被认为是到目前为止唯一的分布式一致性算法,其它的算法都是Paxos的改进或简化。有个问题要提一下,Paxos有一个前提:没有拜占庭将军问题。就是说Paxos只有在一个可信的计算环境中才能成立,这个环境是不会被入侵所破坏的。

详见:https://www.douban.com/note/208430424

扩展 & 可靠性

img

ZAB(Zookeeper Atomic Broadcast)

所有的Zookeeper处理的事物请求必须仅有一个机器来协调处理,这样的机器被称之为Leader服务器,而剩下的其他Zookeeper则称之为Follower,而Leader服务器则是会将客户端的事物请求发给所有的Follwer服务器,等待所有的Follwer服务器的反馈,一旦接受到了超过半数的Follwer服务器的正常完成事物处理的反馈后,Leader服务器就会再次发送一个Commit消息给所有的Follwer服务器,要求将刚刚的事物请求进行提交。

ZAB协议有两种基本的模式,分别为崩溃恢复和消息广播。当整个框架在运行的过程中,或者是当Leader出现网络中断、崩溃重启等异常的情况的时候,ZAB协议就会进入恢复模式,来重新选举一个新的Leader服务器来处理事物请求,当新的Leader服务器选择出来,并且和过半以上的机器实现了状态同步后,ZAB的恢复模式就结束了。这个时候就可以进行ZAB的消息广播模式了,如果在这个过程中有一个新的Zookeeper加入了当前的集群中,就会启动恢复模式,直到实现了和Leader的状态同步为止。

正如上述事物处理的过程一样,Zookeeper中只有Leader可以协调处理事物请求,那么其他的Follower服务器是不是没用了呢?当然不是,在整个Zookeeper集群中,所有的服务器都可以提供对外的请求处理,唯一的区别在于,当Follower服务器接受到了事物请求以后,会转发给Leader,让Leader进行统一处理和协调而已。当然在整个集群的运行过程中会出现很多意外,例如有半数以上的Follower服务器无法与Leader进行正常通信,就会从消息广播模式进入到崩溃恢复模式,从其他的机器中选举一个新的Leader出来,同样的一个Leader的选举必须得到超过半数的机器的支持,所以当整个集群的正常服务的机器超过半数,都可以不停的模式转换,保证集群服务的稳定性,一旦出现问题的机器数量超过了集群的半数,整个集群就不再对外提供事物请求的处理,进入保护模式,仅仅可读。

消息广播

img
原子:成功、失败。没有中间状态(队列+2PC)
广播:分布式多节点的。全部知道!(过半)
队列:FIFO,顺序性
zk的数据状态在内存
用磁盘保存日志

如上图所示:

  • 1, create(ooxx)
    client端发送一个写请求到Follower1
  • 2, create(ooxx)
    Follower1将此写请求转发Leader
  • 3, Zxid:8
    Leader接收到写请求,生成一个递增的事务ID编号:8
    并将Zxid:8 和 写请求写create(ooxx)入队列
  • 4-1, log
    各Follower接收到请求,检查本地的已生效或未生效的Zxid与接收到的Zxid:8比较,本地<=8 拒绝;否则接收;
  • 4-1, ok
    Follower回复Leader我接收此提议,并记录到本地日志;
  • 4-2, write
    Leader收集提议的投票数,过半则生效, 立即给所有Follower发通知提议生效,各Follower收到生效的通知则生成正式的法令;
  • 5,over-ok
    Leader恢复Follower1,集群已执行完写请求
  • 6,ok
    Follower再将Leader的写成功消息转发到Client;
    即使Follower2由于网络延迟未及时接收到写请求,就在此时client发出get请求,有可能获取到版本较老的数据,但可通过sync去向Leader同步数据,再回调client端注册的get方法,从而获取到最新版本的数据

小结:ZAB协议中的消息广播使用的是一个原子广播协议,整体的过程可以看为是一个二阶段提交的过程。客户端的事物请求到来以后,Leader服务器会生成对应的事物Proposal,并且将这个发送给当前集群范围内的其余的所有的机器,并且收集来自所有Follower机器的响应选票信息,而二阶段的过程的具体体现,移除了传统二阶段的中断逻辑处理,因此在收集所有Follower机器的响应过程中,Leader不需要等待所有机器响应后才执行第二阶段,而是只需要等待半数以上的机器返回对应的响应,即可开启第二阶段。当然在这种简化的二阶段过程中,有可能会因为Leader突然奔溃,导致数据不一致的情况,当然出现这种情况就需要启动崩溃恢复机制来处理,并且所有的消息都是具有FIFO特性的TCP协议来进行网络通信的,从而保证消息广播过程中的顺序性。

而在第一阶段,Leader机器会将事物消息生成对应的Proposal进行广播,并且会生成一个单调递增的ID,作为事物的ID(ZXID),由于ZAB协议需要保证事物严格的上下顺序性,所以会严格按照ZXID的先后来处理对应的消息。而在消息广播发起后,Leader会为每一个Follower服务器分配一个单独的队列,然后将需要广播出去的事物Proposal依次存放进这个FIFO的队列中,每个Follower机器收到事物消息后,会按照事物日志的方式写入,成功后反馈给Leader机器Ack响应,当收到半数以上的Ack响应后,Leader就会发起第二阶段的Commit消息给所有的Follower机器,并且这个时候Leader也会和Follower一样进行本地事物的提交操作,完成整个消息的传递和提交。

崩溃恢复

ZK选举过程:
1, 通过3888端口号,完成两两通信!
2, 只要任何人投票,都会触发那个准leader发起自己的投票
3, 推选制:先比较zxid(<本地则拒绝投票),如果zxid相同,再比较myid(比当前myid大则投票+1)

小结:Leader中的已经提交的事物完成同步了,那么未提交的废弃事物怎么剔除呢?在ZAB协议的事物编号ZXID设计中,是一个64位的数字,整体分为低32位和高32位,低32位可以看成一个单调递增的计数器,每一个事物消息生成ID前,低32位都会进行原子的+1操作。而ZXID的高32位代表了epoch的编号,而epoch则是每一次选举出新的Leader的过程中,会从所有的事物ZXID中获取最大的,然后解析出对应的高32位epoch的值,然后将其+1,代表了选举的次数,即Leader的生命周期,并且每一次选举后,epoch+1以后,会将低32位的值清零,作为新的ZXID值。因此当选举触发过程中,有部分机器的ZXID所代表的epoch值较低的时候,这些机器直接会成为Follower,只会有epoch最大并且一样的机器之间进行选举出Leader,而当Leader选举出来以后,所有的Follower连接上Leader以后,会和Leader比较当前最大的Proposal,这个时候Leader根据比较情况要求回滚或者同步Proposal到当前集群中过半机器都提交的最大事物Proposal,至此数据同步操作完成,崩溃恢复模式结束

  • 参考文章
    https://zookeeper.apache.org/doc/current/zookeeperOver.html
    https://www.douban.com/note/208430424/
    ———————————————————
    坐标帝都,白天上班族,晚上是知识的分享者
    如果读完觉得有收获的话,欢迎点赞加关注

你可能感兴趣的:(ZK原理)