ZooKeeper系列:ZAB协议和选举

1,648 阅读5分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

本文ZooKeeper版本:3.8.0

ZooKeper实现数据一致性主要就是依赖其ZAB协议,ZAB协议就是借鉴了Paxos算法

ZAB协议包含两种,分别是原子广播崩溃恢复

原子广播

原子:要么成功,要么失败,不存在中间状态(队列+2阶段提交)

广播:在分布式多节点中,不是所有节点都会接收到广播,但会过半通过。

  1. 客户端发送请求给Follower
  2. 所有的Follower在接收到请求之后,会转发给Leader(所有的事务请求都由Leader来处理)
  3. Leader将会将拿到的请求转化成事务提议,事务序列号Zxid+1。
  4. Leader将提议通过广播给所有的Follower,让其写入日志。(Leader会为每个Follower各设置一个队列,广播的时候把提议放入对应Follower的FIFO队列)
  5. 而Follower的操作结果将反馈给Leader。
  6. Leader在接收到Follower的反馈后,如果集群中有过半的Follower进行正确的ack反馈。Leader将会再次广播Follower ,发送commit消息,提交提议

崩溃恢复

所谓的崩溃恢复 就是在Leader节点崩溃下线后,从有效的Follower节点中推选出一个新的Leader,从而让整个集群继续对外提供服务,在选择的阶段可能会导致各个节点存在数据不一致的问题。

进入崩溃恢复模式的情况

  1. 服务首次启动
  2. 当Leader服务器出现网络/重启等问题导致其无法和过半的服务器正常连接。

恢复模式的策略:

  1. 最先选择zxid最大的节点作为Leader
  2. 新的Leader 会把事务日志中未提交的请求处理掉

Leader选举原理(ZAB有主)

崩溃恢复其实就是选主,有两种情况下的选主,一个是集群首次启动,另一个是运行中Leader崩溃

在选举的时候会参考两个重要的参数:

  • 事务ID(zxid): 值越大说明权重越大,其数据最新
  • 服务器ID(myid): 自定义的服务节点ID,值越大权重越大

过半通过的数据 产生的zxid才是真实有效的

集群首次启动选主

特点:每个节点的数据都是一致的,尤其zxid,不同的是myid

假设此集群共有3个节点,首次启动所以每个节点的zxid都是0,而myid则是不同的1,2,3,所以三个节点的信息分别是node1(1,0),node2(2,0),node3(3,0)。

然后依次启动三个节点,当第二台机器node2启动的时候,node1和node2就可以互相通信的。

  1. node1节点启动 投票(1,0),给自己投1票 ,共三台机器此时未过半,所以没有选出leader,node1的状态是Looking。

    投票结果:node1: 1票

  2. node2节点启动,发起投票(2,0),同时给已经启动的node1节点发送信息(每个节点发起投票的同时也会引发其他的节点再次投票)。

    投票结果: node1: 1票,node2: 1票

  3. node1接收到node2的投票信息,对比zxid和myid,发现node2的myid更大,此时node1就会改选重新投node2

    投票结果:node1:0票,node2: 2票

    对比规则:

    • 比较epoch,来确认是同一轮的投票
    • 再比较zxid,较大的会作为Leader
    • zxid相同再比较myid,较大的作为Leader
  4. 综合现有机器的投票结果,node1是0票,node2是2票(过半)。此时node1的状态是Follower,node2的状态是Leader。

  5. 继续启动node3节点,已经存在Leader,node3会直接加入变更为Follower。

测试:

三台机器的myid分别是1,2,3

如下是三台的端口设置,第一个端口是leader端口,第二端口是leader选举的时候各节点通信的端口

server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2898:3898
server.3=127.0.0.1:2988:3988

先启动node1

5-zk-zab-node1

5-zk-zab-node1-status

没有其他节点和其通信,所以会出现错误,暂时没有节点状态。

启动node2

5-zk-zab-node1-status-following

5-zk-zab-node2-status-leading

随着node2的启动,node1节点也不会出现错误日志,接着变成following状态,而node2变成leading状态

5-zk-zab-node1-status-follower

5-zk-zab-node2-status-leader

接着查看节点状态: node1=follower node2=leader

启动node3

5-zk-zab-node3-status-follower

node3在启动之后 会是following状态,在完成数据同步之后又会变成follower状态

运行中Leader崩溃 选主

特点:每个节点的数据不一定一致的,myid不同,zxid也可能不同

还是上面的3个节点的集群,运行一段时间之后 每个节点的zxid都有了变化分别是4,4,3,myid还是原来的,分别是1,2,3,所以三个节点的信息分别是node1(1,4),node2(2,4),node3(3,3)。node2是Leader节点

这时候如果node2节点因为故障断开连接, 剩下两个节点中任意一个检测到Leader不存了(心跳监控),都会向集群中的其他节点发起投票(投自己,每个节点发起投票的同时也会引发其他的节点再次投票),每个节点在收到其他节点投票信息后比较自己手里的信息 然后选择一个节点进行投票或回复(参考上面的投票方式),最终确定一个Leader。

我是纪先生,用输出倒逼输入而持续学习,持续分享技术系列文章,以及全网值得收藏好文,欢迎关注公众号,做一个持续成长的技术人。