Zookeeper的leader选举,数据一致性与ZAB协议

        ZAB协议Zookeeper Atomic Broadcast(Zookeeper 原子广播协议),Zab协议是为分布式协调服务Zookeeper专门设计的一种 支持崩溃恢复原子广播协议 ,是Zookeeper保证数据一致性的核心算法。整个Zab流程就是消息广播模式切换崩溃恢复模式,Zab借鉴了Paxos算法,但又不像Paxos那样,是一种通用的分布式一致性算法。它是特别为Zookeeper设计的支持崩溃恢复的原子广播协议。

       Zab协议的核心定义了那些会改变ZooKeeper服务器数据状态的事务请求的处理方式

             1)所有的事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被叫做 Leader服务器。其他剩余的服务器则是 Follower服务器。

             2)Leader服务器 负责将一个客户端事务请求,转换成一个 事务Proposal,并将该 Proposal 分发给集群中所有的 Follower 服务器,也就是向所有 Follower 节点发送数据广播请求。

             3)分发之后Leader服务器需要等待所有Follower服务器的反馈(Ack请求),在Zab协议中,只要超过半数的Follower服务器进行了正确的反馈后(也就是收到半数以上的Follower的Ack请求),那么 Leader 就会再次向所有的 Follower服务器发送 Commit 消息,要求其将上一个 事务proposal 进行提交。

        

消息广播模式

1)客户端发起一个写操作请求。

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

zxid编号: 1、低32位为计数器,客户端每次事务请求+1 2、高32位为epochID,每次选举新leader+1                         

3)Leader 服务器为每个 Follower 服务器分配一个单独的队列,然后将需要广播的 Proposal 依次放到队列中取,并且根据 FIFO 策略进行消息发送。

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

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

6)Leader 向所有 Follower 广播 commit 消息,同时自身也会完成事务提交。Follower 接收到 commit 消息后,会将上一条事务提交。

 

 

崩溃恢复模式

         假设两种异常情况: 1、一个事务在 Leader 上提交了,并且过半的 Folower 都响应 Ack 了,但是Leader在commit消息发出给所有的Follower之前,leader服务器挂了。 2、假设一个事务在 Leader 提出之后,Leader 挂了。

要确保如果发生上述两种情况,数据还能保持一致性,那么 Zab 协议选举算法必须满足以下要求:

         Zab 协议崩溃恢复要求满足以下两个要求

         1)确保已经被 Leader 提交的 Proposal 必须最终被所有的 Follower 服务器提交。

         2)确保丢弃已经被 Leader 提出的但是没有被提交的 Proposal。

        根据上述要求 Zab协议需要保证选举出来的Leader需要满足以下条件:

         1)新选举出来的 Leader 不能包含未提交的 Proposal 。 即新选举的 Leader 必须都是已经提交了 Proposal 的 Follower 服务器节点。

         2)新选举的 Leader 节点中含有最大的 zxid 。 这样做的好处是可以避免 Leader 服务器检查 Proposal 的提交和丢弃工作。

         Zab 数据同步过程中,如何处理需要丢弃的 Proposal

在 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。

 

Zab协议要求每个 Leader 都要经历三个阶段:发现,同步,广播

  • 发现:主要就是Leader选举过程,要求zookeeper集群必须选举出一个 Leader 进程,同时 Leader 会维护一个 Follower 可用客户端列表,将来客户端可以和这些 Follower节点进行通信。

  • 同步:Leader 要负责将本身的数据与 Follower 完成同步,做到多副本存储。这样也是提现了CAP中的高可用和分区容错。Follower将队列中未处理完的请求消费完成后,写入本地事务日志中。

  • 广播:Leader 可以接受客户端新的事务Proposal请求,将新的Proposal请求广播给所有的 Follower。

    正常运行过程中,ZAB协议会一直运行于阶段三来反复地进行消息广播流程。如果出现Leader崩溃或者其他原因导致Leader缺失,那么此时ZAB协议再次进入阶段一从新选举Leader

 各消息说明依次如下:

 

      在ZAB协议的设计中,每个进程都有可能处于以下状态之一。

          1、Looking:系统刚启动时或者Leader崩溃后正处于选举状态

          2、Following:Follower节点所处的状态,Follower与Leader处于数据同步阶段

          3、Leading:Leader所处状态,当前集群中有一个Leader为主进程

       

          Zookeeper 的Leader选举过程:

         服务器启动阶段的Leader选举 :三台服务器集群

         当第一台服务器(myid为1,Server1)启动的时候,无法完成leader选举,当第二台机器(myid为2,Server2)也启动后,这两台机器能够进行相互通信,每台机器都试图找到leader,开始进入leader选举

          1.每个server发出投票

          由于是初始情况,因此队医server1和server2来说,都回将自己作为leader服务器来进行投票,每次投票的内容包含(myid,zxid),开始它们都会投给自己,即server1的投票为(1,0),server2的投票为(2,0),然后将投票发给集群中的其他服务器。

         2.接受到每个服务器的投票和处理投票

         首先检查投票的有效性,是否是本轮投票,是否来自LOOKING状态的服务器

         然后将自己的投票和别人的pk,优先检查zxid,大的为leader,如果zxid相同的话,比较myid,大的为leader服务器,于是服务器server1更新自己的投票为(2,0),然后将投票发出去,对于server2来说,不需要更新自己的投票信息,只是再一次向集群中所有机器发出上一次投票的信息即可

         3.统计投票

         每次投票后,服务器都会统计所有投票,判断是否已经有过半的机器接收到相同的投票信息,对于server1和server2服务器来说,都统计出集群中已经有两台机器接受了(2,0)投票信息,达到了“过半”的要求,那么server1和server2收到了相同的投票信息(2,0)的时候,已经选出了leader。

        4.改变服务器的状态

        一旦确定了leader,每个服务器会更新自己的状态,如果是follower,更新为following,如果是leader,那么更新为leading。

 

       服务器运行期间的Leader选举:三台服务器集群

       某一瞬间,Leader挂了,这个时候变开始Leader选举

       1.变更状态

          当Leader挂了之后,余下的服务器状态变更为LOOKING,然后进入Leader选举流程。

       2.每一个Server发出一个投票

          生成投票信息(myid,ZXID),因为是运行期间,每个服务器的ZXID可能不同,我们假定Server1的ZXID为123,而Server3的ZXID为122。在第一轮投票中,他们都会投自己,然后将投票发给集群中的所有机器。

       3.接收来个每个服务器的投票

       4.处理投票

          对于投票的处理,和上面服务器启动期间的处理规则是一致的。Server1的ZXID为123,而Server3的ZXID为122,那么显然,Server1成为Leader。

       5.统计投票

      6.改变服务器状态

          简单地说,通常哪台服务器上的数据越新,那么越有可能成为Leader,原因很简答,数据越新,那么ZXID就越大,越能保证数据的恢复。如果ZXID一致,则myid大的为Leader。

 

          本文参考内容来源:《从Paxos到Zookeeper  分布式一致性原理与实践 》

posted @ 2019-07-01 16:54  Don'tYouSee  阅读(503)  评论(0)    收藏  举报