一致性协议有很多种,比如Paxos,Raft,2PC,3PC等等,zk主要使用的是ZAB.
Zookeeper Atomic Broadcast(Zookeeper 原子广播协议).
它是为分布式协调服务 Zookeeper 专门设计的一种支持崩溃恢复和原子广播协议.
zk会给每个事物分配一个zxid,一个64位数字,前32位epoch,后32位counter,每次执行事务counter+1,当每次选举更换leader时,epoch+1,原后32位counter的数字会被重置为0.
高32位代表了每代Leader的唯一性,低32代表了每代 Leader中事务的唯一性。同时,也能让 Follwer 通过高 32 位识别不同的 Leader。简化了数据恢复流程。
基于这样的策略:当Follower链接上Leader之后,Leader服务器会根据自己服务器上最后被提交的ZXID和Follower上的ZXID进行比对,比对结果要么回滚,要么和Leader同步。
zk的同步数据的过程类似于2PC(两段式提交)
首先提交写事务到集群leader中,由leader广播,收到一半以上节点ack的返回时,该写请求事务就会同时commit.同时写入leader和follower中.
ZAB设计了下面这样一个选举算法:能够确保提交已经被Leader提交的事务,同时丢弃已经被跳过的事务。
针对这个要求,如果让Leader选举算法能够保证新选举出来的Leader服务器拥有集群总所有机器编号(即ZXID最大)的事务,那么就能够保证这个新选举出来的Leader一定具有所有已经提交的提案.而且这么做有一个好处是:可以省去Leader服务器检查事务的提交和丢弃工作的这一步操作.
1.选epoch最大的.
2.epoch相等,选zxid最大的.
3.epoch和zxid都相等,选择serverId最大的(就是我们配置zoo.cfg中的myid).
zk各个节点刚开始处于选举状态,当有节点获取一半的票数时,则该节点升级成准leader.
准leader将生成一个新的epoch值,通过通信告诉所有的follower.
各个follower获取到新的zxid时,会从leader中同步数据,每个follower只会同步比自己lastZXID大的数据.保证每个节点的数据一致性.
这个时候leader可以对整个集群,进行事务广播.
由于zk使用的是类似于2PC的原子广播机制,但如果集群节点过多,这个机制限制了集群的效率.
leader 的选举只需要超过半数的节点投票即可,这样不需要等待所有节点的选票,能够尽早选出 leader。
当leader服务器出现,宕机,网络中断时,zk集群会选举出一个zxid最大的节点做leader,leader开始同步数据,follower对根据自己的LastZxid和leader的zxid做比较,小于时同步缺失的事务,当有一半的follower同步完成时.则进入广播模式.