ZAB算法

什么是zab算法

zab协议全称为zookeeper atomic boradcast(原子广播协议)

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选举

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

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

谁的票数最多谁就会变为leader 前提是票数是超过节点机器的半数

消息广播流程

zxid

​ zxid 是一个用于标识事务的唯一标识符。每个事务在ZooKeeper中都会被分配一个唯一的ZXID。

​ ZXID由两部分组成:高位部分表示事务的Epoch(选举轮次),低位部分表示事务的序列号。Epoch是在领导者选举过程中使用的概念,用于区分不同的选举周期。序列号用于在选举周期内对事务进行排序

当一个节点成为ZooKeeper集群的领导者时,它会生成具有较高Epoch值的ZXID。在该选举周期内,领导者生成的所有事务都具有较高的Epoch值。当选举周期结束并发生新的选举时,新领导者会增加Epoch值,以区分新的选举周期。

ZXID在ZooKeeper中的使用非常重要。它用于确定事务的顺序和一致性。比较两个ZXID可以确定哪个事务先发生,从而保证了数据的正确顺序和一致性。

总之,ZXID是ZooKeeper中用于标识事务的唯一标识符,由Epoch和序列号组成,用于维护事务的顺序和一致性。

  1. Leader 接收到消息请求后,将消息赋予一个全局唯一的 64 位自增 id,叫做:zxid,通过 zxid 的大小比较即可实现因果有序这一特性。
  2. Leader 通过先进先出队列(通过 TCP 协议来实现,以此实现了全局有序这一特性)将带有 zxid 的消息作为一个提案(proposal)分发给所有 follower。
  3. 当 follower 接收到 proposal,先将 proposal 写到硬盘,写硬盘成功后再向 leader 回一个 ACK。
  4. 当 leader 接收到合法数量的 ACKs 后,leader 就向所有 follower 发送 COMMIT 命令,同时会在本地执行该消息。
  5. 当 follower 收到消息的 COMMIT 命令时,就会执行该消息。

相比于完整的二阶段提交,Zab 协议最大的区别就是不能终止事务,follower 要么回 ACK 给 leader,要么抛弃 leader,在某一时刻,leader 的状态与 follower 的状态很可能不一致,因此它不能处理 leader 挂掉的情况,所以 Zab 协议引入了恢复模式来处理这一问题。

从另一角度看,正因为 Zab 的广播过程不需要终止事务,也就是说不需要所有 follower 都返回 ACK 才能进行 COMMIT,而是只需要合法数量(2n+1 台服务器中的 n+1 台) 的follower,也提升了整体的性能。

奔溃恢复流程

zookeeper崩溃恢复有两个场景

  • Zookeeper服务器启动时Leader选举。
  • Zookeeper集群运行过程中Leader崩溃后的Leader选举。
leader选举参数
  1. myid: 服务器ID,这个是在安装Zookeeper时配置的,myid越大,该服务器在选举中被选为Leader的优先级会越大。ZAB算法中通过myid来规避了多个节点可能有相同zxid问题,注意可以对比之前的Raft算法,Raft算法中通过随机的timeout来规避多个节点可能同时成为Leader的问题。
  2. zxid: 事务ID,这个是由Zookeeper集群中的Leader节点进行Proposal时生成的全局唯一的事务ID,由于只有Leader才能进行Proposal,所以这个zxid很容易做到全局唯一且自增。因为Follower没有生成zxid的权限。zxid越大,表示当前节点上提交成功了最新的事务,这也是为什么在崩溃恢复的时候,需要优先考虑zxid的原因。
  3. epoch: 投票轮次,每完成一次Leader选举的投票,当前Leader节点的epoch会增加一次。在没有Leader时,本轮此的epoch会保持不变
选举流程

​ 1.每个Server会发出一个投票,第一次都是投自己。投票信息:(myid,ZXID)

​ 2.收集来自各个服务器的投票

​ 3.处理投票并重新投票,处理逻辑:优先比较ZXID,然后比较myid

​ 4.统计投票,只要超过半数的机器接收到同样的投票信息,就可以确定leader

​ 5.改变服务器状态,进入正常的消息广播流程。

如果保证数据的一致性?
什么情况下会出现的数据不一致性?

当 leader 收到合法数量 follower 的 ACKs 后,就向各个 follower 广播 COMMIT 命令,同时也会在本地执行 COMMIT 并向连接的客户端返回「成功」。但是如果在各个 follower 在收到 COMMIT 命令前 leader 就挂了,导致剩下的服务器并没有执行都这条消息。

答案:

我的理解是这样的。 当前leader同步的该条数据没有被follower提交就挂了。 然后follower中就选举出来的一个新的leader 此时是不是在对外提供服务中,刚才写入的数据是无法获取到的?因为此时该leader节点的那条数据并没有被提交?。。 如果此后原leader节点启动了,是如何把刚才的那条数据的提交操作与其它节点处理的呢?

所以zookeeper zab协议还是一个最终实现一致性的实现是吧。 我可以保证各个节点数据完全一致,但是在特殊情况下(就比如我刚才描述的情况下) 是会有延迟的(我感觉是这样的 还是一个最终一致性的实现)

你可能感兴趣的:(java,zookeeper,zab,分布式算法)