Zookeeper的leader选举和数据同步

目录

ZAB 协议

消息广播

崩溃恢复

Leader选举过程

ZXID

在zookeeper的集群中,客户端会随机连接到一个节点。

如果是读请求,就直接在该节点读取数据;如果是写请求,则这个请求会被转发到leader节点提交事务,然后leader节点会广播事务,若所有节点超过半数写入成功,则请求会被提交。

过程解释:

客户端client发出一个请求(写请求)给其中一个follower节点,这个follower节点将这个请求转发给leader节点。此时leader节点会消息作为一个提案(proposal)分发给所有的 follower,

当 follower 接收到 proposal,先把 proposal 写到磁盘,写入成功以后再向 leader 回复一个 ack,当 leader 接收到合法数量(超过半数节点)的 ACK 后,leader 就会向这些 follower 发送 commit 命令,

同时会在本地执行该消息,当 follower 收到消息的 commit 命令以后,会提交该消息。

ZAB 协议

ZAB(Zookeeper Atomic Broadcast) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。

基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。

ZAB 协议包含两种基本模式:崩溃恢复和原子广播

在集群启动或leader网络中断、崩溃等情况。ZAB会进入恢复模式,选举leader,leader选举出之后,若有过半的机器与leader完成数据同步后,ZAB协议退出恢复模式。

当有过半的follower节点和leader节点完成数据同步后,集群会进入消息广播模式。

消息广播

  • leader接收到消息(客户端直接请求,或者follower接收到消息后转发给leader)后,将消息赋予一个64位自增的全局唯一id,这个id叫做:zxid,从而实现消息的有序性。
  • leader 为每个 follower 准备了一个 FIFO 队列将带有 zxid的消息作为一个提案(proposal)分发给所有的 follower。
  • 当 follower 接收到 proposal,先把 proposal 写到磁盘,写入成功以后再向 leader 回复一个 ack
  • 当 leader 接收到超过半数节点数的 ACK 后,leader 就会向这些 follower 发送 commit 命令,同时会在本地执行该消息。
  • 当 follower 收到消息的 commit 命令以后,会提交该消息

leader不需要Observer(观察者节点)的ack,但是Observer需要同步leader节点的数据,从而在处理请求时保证数据的一致性。

崩溃恢复

之前的消息广播,在正常情况下没有任何问题,但是如果leader节点崩溃,或者由于网络问题 Leader 服务器失去了过半的 Follower 节点的联系,那么就会进入到崩溃恢复模式。

此时,在崩溃恢复状态下,ZAB会做两件事情:选举出新的 leader以及数据同步

在数据同步时,要保证两件事情:已经发出commit的不能被丢弃、没有发出commit的(leader节点只提出了proposal或者还没有commit)需要丢弃。

ZAB 协议需要满足上面两中情况,使用了以下策略:

  • 选举zxid最大的节点作为新的leader,由于所有提案被 COMMIT 之前必须有合法数量的 follower ACK,即必须有合法数量的服务器的事务日志上有该提案的 proposal,因此,只要有合法数量的节点正常工作,就必然有一个节点保存了所有被 COMMIT 消息的 proposal 状态。
  • 新的 leader 与 follower 建立先进先出的队列, 先将自身有而 follower 没有的 proposal 发送给 follower,再将这些 proposal 的 COMMIT 命令发送给 follower,以保证所有的 follower 都保存了所有的 proposal、所有的 follower 都处理了所有的消息。通过以上策略,能保证已经被处理的消息不会丢
  • 当 leader 接收到消息但未commit,此时这些消息在启动后会被删除。

Leader选举过程

若进行Leader选举,则至少需要两台机器,这里选取3台机器组成的服务器集群为例。在集群初始化阶段,当有一台服务器Server1启动时,其单独无法进行和完成Leader选举,当第二台服务器Server2启动时,此时两台机器可以相互通信,每台机器都试图找到Leader,于是进入Leader选举过程。选举过程如下

 (1) 每个Server发出一个投票。由于是初始情况,Server1和Server2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,此时Server1的投票为(1, 0),Server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。

  (2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。

  (3) 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下

    · 优先检查ZXID。ZXID比较大的服务器优先作为Leader。

    · 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。

  对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的ZXID,均为0,再比较myid,此时Server2的myid最大,于是更新自己的投票为(2, 0),然后重新投票,对于Server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。

  (4) 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于Server1、Server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了Leader。

  (5) 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。

\2. 服务器运行时期的Leader选举

 在Zookeeper运行期间,Leader与非Leader服务器各司其职,即便当有非Leader服务器宕机或新加入,此时也不会影响Leader,但是一旦Leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮Leader选举,其过程和启动时期的Leader选举过程基本一致。假设正在运行的有Server1、Server2、Server3三台服务器,当前Leader是Server2,若某一时刻Leader挂了,此时便开始Leader选举。选举过程如下

  (1) 变更状态。Leader挂后,余下的非Observer服务器都会讲自己的服务器状态变更为LOOKING,然后开始进入Leader选举过程。

  (2) 每个Server会发出一个投票。在运行期间,每个服务器上的ZXID可能不同,此时假定Server1的ZXID为123,Server3的ZXID为122;在第一轮投票中,Server1和Server3都会投自己,产生投票(1, 123),(3, 122),然后各自将投票发送给集群中所有机器。

  (3) 接收来自各个服务器的投票。与启动时过程相同。

  (4) 处理投票。与启动时过程相同,此时,Server1将会成为Leader。

  (5) 统计投票。与启动时过程相同。

  (6) 改变服务器的状态。与启动时过程相同。

上边选出的只是准leader,要想变成leader还需完成数据同步。

同步阶段主要是利用 leader 前一阶段获得的最新提议历史,同步集群中所有的副本。只有当 集群过半机器都同步完成,准 leader 才会成为真正的 leader。follower 只会接收 zxid 比自己的 lastZxid 大的提议

当完成Leader选举后,进行故障恢复的第二步就是数据同步: Leader服务器会为每一个Follower服务器准备一个队列,并将那些没有被各个Follower服务器同步的事务以Proposal的形式逐条发给各个Follower服务器,并在每一个Proposal后都紧跟一个commit消息,表示该事务已经被提交,档follower服务器将所有尚未同步的事务proposal都从leader服务器同步过来并成功应用到本地后,leader服务器就会将该follower加入到真正可用的follower列表中。

ZXID

 zxid,也就是事务 id。

为了保证事务的顺序一致性,zookeeper 采用了递增的事务 id 号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了 zxid。

实现中 zxid 是一个 64 位的数字,它高 32 位是 epoch(ZAB 协议通过 epoch 编号来区分 Leader 周期变化的策略)用来标识 leader 关系是否改变,每次一个 leader 被选出来,它都会有一个新的epoch=(原来的 epoch+1),标识当前属于那个 leader 的统治时期。低 32 位用于递增计数。

 

 

 

 

 

 

 

 

 

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值