Zookeeper技术原理(三):Leader选举及数据同步

Zookeeper技术原理(三):Leader选举及数据同步,第1张

Zookeeper技术原理(三):Leader选举及数据同步 Leader选举 服务端之间IO

在每台服务器启动的时候,都会启动一个QuorumCnxmanager,负责各台服务器之间的底层Leader选举过程中的网络通信。QuorumCnxmanager在启动的时候,会去与其它的服务端建立TCP连接,为了避免重复建立连接ZK只允许SID大的服务端主动和其他服务器建立连接,否则断开连接。QuorumCnxmanager内部维护了以下内容:

发生Leader选举的时机
  1. 服务端刚启动时;
  2. 服务端运行时Leader挂了,通过心跳消息来发现Leader挂了。ZK一旦选出一个Leader,那么即使集群中有其它机器加入或退出,该Leader将一直作为集群的Leader不变,但是如果Leader挂了,那么整个集群将暂时无法对外服务,而是进入新一轮的Leader选举;
选举Leader时集群状态
  1. 没有Leader,则正常进行Leader选举;
  2. 集群存在一个Leader,则该服务端发送投票后会被告知当前集群中存在一个Leader以及当前Leader的信息,此时变为Follower即可;
选票vote的内容

ZXID如何计算

ZXID是一个64位的数字,其中低32位可以看做是一个简单的单调递增的计数器,针对客户端的每一个事务请求,Leader服务器在产生一个新的事务Proposal时,都会对该计数器进行加1 *** 作;而高32位则代表了Leader周期epoch的编号,每当选举产生一个新的Leader时,就会从这个Leader上取出其本地日志中最大事务Proposal的ZXID,并解析出epoch值,然后加1,之后以该编号作为新的epoch,并将低32位置0开始生成新的ZXID。

具体的选举流程(重点)
  1. 在选举开始时,除了Observer外,所有的服务器状态都会变为Looking;
  2. 首先所有的服务器都会选举自己作为Leader,然后将这张选票发送给其它所有服务端;
  3. 从接收队列中获取来自其它服务器的投票,并对接收到的选票进行如下处理:
    首先判断选举轮次(每开始一轮选举投票都会将选举轮次自增,只有在同一个选举轮次中的选票才是有效的):①如果接收到的选票的选举轮次大于本地的选举轮次,则更新本地的选举轮次并清空已经接收到的选票,然后将自己作为候选Leader和选票中的Leader进行PK,将胜出者更新为本地选票并将其广播出去;②如果接收到的选票的选举轮次小于本地的选举轮次,则不做任何处理,直接忽略该选票,继续接收选票;③收到的选票选举轮次和本地一致,则对本地选票和接收到的选票进行PK,然后将本地选票更新为胜出者并将其广播出去。
    PK过程为:先比较ZXID,大的胜出;如果ZXID相等,则比较SID,大的胜出;
  4. 无论是否对本地选票进行了变更,都会将刚接收到的选票放入选票集合中,进行选票归档;
  5. 对选票集合进行统计,判断是否有服务器获得了半数以上的服务器的投票,如果有则终止投票,否则返回步骤3继续循环;
  6. 投票流程结束后,如果统计出的结果为自己,则将自己的状态变更为Leader,否则变更为Follower或Observer;
选举完成后地处理(重点)
  1. 其它服务器(Learner)向Leader发起TCP连接请求,Leader为每一个建立了连接地服务端创建一个LearnerHandler,该handle对应Leader和一个服务器地连接,由它负责完成两者之间地消息通信和数据同步;
  2. 建立起连接后,Learner向Leader发起注册,即将自己的信息发送给Leader。Leader更新完epoch后,会将自己的信息发送给Learner,然后Learner收到后回送一个Ack消息;
  3. Leader收到Ack消息后,会开始与其进行数据同步,当Leader与半数以上的服务端完成数据同步后,集群就可以对外提供服务了;
数据同步(重点)

ZK服务端维护一个最近提交的事务的队列committedLog,Leader主要通过committedLog中最小的ZXID即minCommittedLog、committedLog中最大的ZXID即maxCommittedLog、Learner服务器最后处理的事务的ZXID即peerLastZxid这3个元素来完成与Learner的数据同步,具体来说有以下4中方式:

  1. peerLastZxid介于minCommittedLog和maxCommittedLog之间,使用直接差异化同步(DIFF同步)。Leader首先向这个Learner发送一个DIFF指令,通知Learner进入差异化数据同步阶段,然后将peerLastZxid到maxCommittedLog之间的事务发送给Learn,针对每个Proposal,Leader都会通过发送PROPOSAL内容数据包和COMMIT指令数据包来完成;
  2. 在情况1的基础上,Leader发现Learner包含一条自己没有的事务记录(例如该Learn之前是Leader产生了一个Proposal但是并没有广播给其它服务器就挂了,然后现在又恢复了的场景),使用先回滚再差异化同步(TRUNC+DIFF同步),先让该Learner进行事务回滚,回滚到Leader服务器上存在的,同时也是最接近于peerLastZxid的ZXID,然后再使用差异化同步;
  3. peerLastZxid大于maxCommittedLog,使用仅回滚同步(TRUNC同步),Leader要求Learner回滚到ZXID值为maxCommittedLog对应的事务 *** 作;
  4. peerLastZxid小于minCommittedLog或Leader服务器上没有committedLog队列,使用全量同步(SNAP同步),Leader首先向Learner发送一个SNAP指令,通知Learner即将进行全量同步,然后Leader会从内存数据库中获取到全量的数据节点,将他们序列化后传输给Learner,Learner接收到该全量数据后,对其反序列化后载入到内存数据库中;

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5676332.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存