二十7、Zookeeper的内部原理与ZAB协议

本文主要讲述Zookeeper的内部原理以及ZAB协议,Zookeeper算是大数据中的一个协做框架,比较简单,本文应该是Zookeeper部分的最后一篇文章。关注专栏《破茧成蝶——大数据篇》,查看更多相关的内容~html


目录node

1、Zookeeper的内部原理算法

1.1 节点类型服务器

1.2 Stat结构体网络

1.3 监听器session

1.4 写数据流程架构

1.5 Zookeeper的选举机制框架

2、ZAB协议异步

2.1 ZAB协议是什么分布式

2.2 ZAB协议的做用

2.3 ZAB协议的原理

2.4 ZAB协议的工做

2.4.1 消息广播

2.4.2 崩溃恢复

2.5 ZAB数据同步


 

1、Zookeeper的内部原理

1.1 节点类型

Zookeeper的节点类型能够分为两种:持久型和短暂型。持久型指当客户端与服务器断开链接后,该节点不会删除;短暂型指当客户端与服务器断开链接后,该节点也会随之删除。

1.2 Stat结构体

 Stat结构体在《二11、Zookeeper的命令行操做》中已经有提到过了,可是这里得再次不厌其烦的说一下。

       (1)cZxid:建立节点的事务zxid。每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。事务ID是ZooKeeper中全部修改总的次序。每一个修改都有惟一的zxid,若是zxid1小于zxid2,那么zxid1在zxid2以前发生。
       (2)ctime:znode被建立的毫秒数(从1970年开始)。
       (3)mZxid:znode最后更新的事务zxid。
       (4)mtime:znode最后修改的毫秒数(从1970年开始)。
       (5)pZxid:znode最后更新的子节点zxid。
       (6)cversion:znode子节点变化号,znode子节点修改次数。
       (7)dataVersion:znode数据变化号。
       (8)aclVersion:znode访问控制列表的变化号。
       (9)ephemeralOwner:若是是临时节点,这个是znode拥有者的session id。若是不是临时节点则是0。
       (10)dataLength:znode的数据长度。
       (11)numChildren:znode子节点数量。









1.3 监听器

一、首先在main()线程中建立Zookeeper客户端,这时会同时建立两个线程:一个用于网络链接通讯(A),一个用于监听(B)。

二、经过A线程将注册的监听事件发送个Zookeeper,这时Zookeeper会将注册的监听事件添加到注册监听器列表。

三、Zookeeper监听到有数据或者路径等等的变化,就会将这个消息发送给B线程。

1.4 写数据流程

一、客户端向Zookeeper的服务器上写数据,首先会发送一个写请求。

二、若是接收到该请求的服务器(A)不是Leader服务器,那么它会将这个请求转发给Leader服务器,这时Leader服务器会将请求广播给集群内的其余服务器。各个服务器会将写请求加入待写队列,并向Leader服务器发送成功的信息。

三、当Leader服务器收到半数以上的Follower服务器的成功信息后,说明该写操做能够执行。这是Leader会向各个Follower发送提交信息,各个Follower收到信息后,会落实队列里面的写请求,此时写入成功。

四、服务器A通知客户端数据写入成功。

1.5 Zookeeper的选举机制

选举机制遵循半数机制,即:集群中半数以上机器存活,集群就是可用状态,因此Zookeeper适合安装奇数台服务器。Zookeeper虽然在配置文件中并无指定Master和Slave。可是,Zookeeper工做时,是有一个节点为Leader,其余则为Follower,Leader是经过内部的选举机制临时产生的。例若有五台服务器(A-E)组成的Zookeeper集群,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是同样的。假设这些服务器依次启动,那么会发生下面的状况:

一、服务器A启动,发起一次选举。服务器A投本身一票。此时服务器A票数一票,不够半数以上(3票),选举没法完成,服务器A状态保持为LOOKING。

二、服务器B启动,再发起一次选举。服务器A和B分别投本身一票并交换选票信息:此时服务器A发现服务器B的ID比本身目前投票推举的(服务器A)大,更改选票为推举服务器B。此时服务器A票数0票,服务器B票数2票,没有半数以上结果,选举没法完成,服务器A、B状态保持LOOKING。

三、服务器C启动,发起一次选举。此时服务器A和B都会更改选票为服务器C。这次投票结果:服务器A为0票,服务器B为0票,服务器C为3票。此时服务器C的票数已经超过半数,服务器C当选Leader。服务器A、B更改状态为FOLLOWING,服务器C更改状态为LEADING。

四、服务器D启动,发起一次选举。此时服务器A、B、C已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器C为3票,服务器D为1票。此时服务器D服从多数,更改选票信息为服务器C,并更改状态为FOLLOWING。

五、服务器E启动,过程同4。

2、ZAB协议

2.1 ZAB协议是什么

ZAB协议的全称是Zookeeper Atomic Broadcast(Zookeeper原子广播)。Zookeeper是经过ZAB协议来保证分布式事务的最终一致性。ZAB协议是为分布式协调服务Zookeeper专门设计的一种支持崩溃恢复的原子广播协议,是Zookeeper保证数据一致性的核心算法。ZAB借鉴了Paxos算法,但又不像Paxos算法那样,是一种通用的分布式一致性算法。它是特别为Zookeeper设计的支持崩溃恢复的原子广播协议。

在Zookeeper中主要依赖ZAB协议来实现数据一致性,基于该协议,Zookeeper实现了一种主备模型(即Leader和Follower模型)的系统架构来保证集群中各个副本之间数据的一致性。这里的主备系统架构模型,就是指只有一台客户端(Leader)负责处理外部的写事务请求,而后Leader客户端将数据同步到其余Follower节点。Zookeeper客户端会随机的连接到Zookeeper集群中的一个节点,若是是读请求,就直接从当前节点中读取数据;若是是写请求,那么节点就会向Leader提交事务,Leader接收到事务提交,会广播该事务,只要超过半数节点写入成功,该事务就会被提交。

ZAB协议的特性:

一、ZAB协议须要确保那些已经在Leader服务器上提交的事务最终被全部的服务器提交。

二、ZAB协议须要确保丢弃那些只在Leader上被提出而没有被提交的事务。

2.2 ZAB协议的做用

一、当主进程出现异常的时候,整个Zookeeper集群依旧可以正常工做。

二、使用一个Leader来接收并处理客户端的事务请求,并采用ZAB的原子广播协议,将服务器数据的状态变动以事务proposal(事务提议)的形式广播到全部的Follower进程上去。

三、保证一个全局的变动序列被顺序引用。Zookeeper是一个树形结构,不少操做都要先检查才能肯定是否能够执行,为了保证这一点,ZAB要保证同一个Leader发起的事务要按顺序被请求,同时还要保证只有先前Leader的事务被请求以后,新选举出来的Leader才能再次发起事务。

2.3 ZAB协议的原理

ZAB协议要求每一个Leader都要经历三个阶段:发现、同步、广播。

发现阶段要求Zookeeper集群必须选举出一个Leader,同时Leader会维护一个Follower可用客户端列表。未来客户端能够和这些Follower节点进行通讯。同步阶段Leader要负责将自己的数据与Follower完成同步,作到多副本存储。Follower将队列中未处理完的请求消费完成后,写入本地事务日志中。广播阶段Leader能够接受客户端新的事务Proposal请求,将新的Proposal请求广播给全部的Follower。

ZAB协议定义了事务请求的处理方式:全部的事务请求必须由一个全局惟一的服务器来协调处理,这样的服务器被叫作Leader服务器。其余剩余的服务器则是Follower服务器。Leader服务器负责将一个客户端事务请求,转换成一个事务Proposal,并将该Proposal分发给集群中全部的Follower服务器,也就是向全部 Follower节点发送数据广播请求。分发以后Leader服务器须要等待全部Follower服务器的反馈,在ZAB协议中,只要超过半数的Follower服务器进行了正确的反馈后,那么Leader就会再次向全部的Follower服务器发送Commit消息,要求其将上一个事务proposal进行提交。这也就是上文中1.4提到的写数据流程。

2.4 ZAB协议的工做

当整个集群启动过程当中,或者当Leader服务器出现网络中弄断、崩溃退出或重启等异常时,ZAB协议就会进入崩溃恢复模式,选举产生新的Leader。当选举产生了新的Leader,同时集群中有过半的机器与该Leader服务器完成了状态同步(即数据同步)以后,ZAB协议就会退出崩溃恢复模式,进入消息广播模式。这时,若是有一台遵照ZAB协议的服务器加入集群,由于此时集群中已经存在一个Leader服务器在广播消息,那么该新加入的服务器自动进入恢复模式:找到Leader服务器,而且完成数据同步。同步完成后,做为新的Follower一块儿参与到消息广播流程中。

当Leader出现崩溃退出或者机器重启,亦或是集群中不存在超过半数的服务器与Leader保存正常通讯,ZAB协议就会再一次进入崩溃恢复,发起新一轮Leader选举并实现数据同步。同步完成后又会进入消息广播模式,接收事务请求。在整个消息广播中,Leader会将每个事务请求转换成对应的proposal来进行广播,而且在广播事务Proposal以前,Leader服务器会首先为这个事务Proposal分配一个全局单递增的惟一ID,称之为事务ID(即zxid),因为ZAB协议须要保证每个消息的严格的顺序关系,所以必须将每个proposal按照其zxid的前后顺序进行排序和处理。

2.4.1 消息广播

消息广播的步骤以下:

一、客户端发起一个写操做请求。

二、Leader服务器将客户端的请求转化为事务Proposal提案,同时为每一个Proposal分配一个全局的ID,即zxid。

三、Leader服务器为每一个Follower服务器分配一个单独的队列,而后将须要广播的Proposal依次放到队列中去,而且根据FIFO策略进行消息发送。

四、Follower接收到Proposal后,会首先将其以事务日志的方式写入本地磁盘中,写入成功后向Leader反馈一个Ack响应消息。

五、Leader接收到超过半数以上Follower的Ack响应消息后,即认为消息发送成功,能够发送commit消息。

六、Leader向全部Follower广播commit消息,同时自身也会完成事务提交。Follower接收到commit消息后,会将上一条事务提交。

Zookeeper采用ZAB协议的核心,就是只要有一台服务器提交了Proposal,就要确保全部的服务器最终都能正确提交Proposal。Leader服务器与每个Follower服务器之间都维护了一个单独的FIFO消息队列进行收发消息,使用队列消息能够作到异步解耦。Leader和Follower之间只须要往队列中发消息便可。若是使用同步的方式会引发阻塞,性能要降低不少。

2.4.2 崩溃恢复

一旦Leader服务器出现崩溃或者因为网络缘由致使Leader服务器失去了与过半Follower的联系,那么就会进入崩溃恢复模式。在ZAB协议中,为了保证程序的正确运行,整个恢复过程结束后须要选举出一个新的Leader服务器。

ZAB协议崩溃恢复要求知足两个要求:一、确保已经被Leader提交的Proposal必须最终被全部的Follower服务器提交。二、确保丢弃已经被Leader提出的可是没有被提交的Proposal。根据上述要求ZAB协议须要保证选举出来的Leader知足如下条件:一、新选举出来的Leader不能包含未提交的Proposal。即新选举的Leader必须都是已经提交了Proposal的Follower服务器节点。二、新选举的Leader节点中含有最大的zxid。

2.5 ZAB数据同步

一、完成Leader选举后新的Leader具备最高的zxid,在正式开始工做以前(接收事务请求,而后提出新的Proposal),Leader服务器会首先确认事务日志中的全部的Proposal是否已经被集群中过半的服务器Commit。

二、Leader服务器须要确保全部的Follower服务器可以接收到每一条事务的Proposal,而且能将全部已经提交的事务Proposal应用到内存数据中。等到Follower将全部还没有同步的事务Proposal都从Leader服务器上同步过来而且应用到内存数据中之后,Leader才会把该Follower加入到真正可用的Follower列表中。

在ZAB的事务编号zxid设计中,zxid是一个64位的数字。其中低32位能够当作一个简单的单增计数器,针对客户端每个事务请求,Leader在产生新的Proposal事务时,都会对该计数器加1。而高32位则表明了Leader周期的epoch编号。epoch编号能够理解为当前集群所处的年代或者周期。每次Leader变动以后都会在epoch的基础上加1,这样旧的Leader崩溃恢复以后,其余Follower也不会听它的,由于Follower只服从epoch最高的Leader命令。每当选举产生一个新的Leader,就会从这个Leader服务器上取出本地事务日志中最大编号Proposal的zxid,并从zxid中解析获得对应的epoch编号,而后再对其加1,以后该编号就做为新的epoch值,并将低32位数字归零,由0开始从新生成zxid。ZAB协议经过epoch编号来区分Leader变化周期,可以有效避免不一样的Leader错误的使用了相同的zxid编号提出了不同的Proposal的异常状况。基于以上策略当一个包含了上一个Leader周期中还没有提交过的事务Proposal的服务器启动时,当这台机器加入集群中,以Follower角色连上Leader服务器后,Leader服务器会根据本身服务器上最后提交的Proposal来和Follower服务器的Proposal进行比对,比对的结果确定是Leader要求Follower进行一个回退操做,回退到一个确实已经被集群中过半机器Commit的最新Proposal。

 

到这本文基本上接近尾声了,这篇文章理论描述居多,可能会比较枯燥,大家有什么问题,欢迎留言,让我看看大家都有哪些问题~

相关文章
相关标签/搜索