zk的ZAB原子广播协议来源于paxos算法[1]。paxos算法是一种基于消息传递的消息一致性算法,其特点是在可靠的通信环境下,可以保证消息的最终一致性。paxos要求每台server都持有自己的一个事务id的记录,这个事务id会每通过一个提议就自增加一,并可以通过事务id来判断提议是否应该投票,如果提议的事务id小于当前自己记录的事务id,那么就不投票。不过paxos中没有leader的概念,每个server之间都是平等的,为了简化或者说优化paxos,zk中有了Leader的概念,最终是否投票通过,由leader最终决定。
那么zk的zab协议是如何运作的呢?介绍如下。
1、zk正常工作
对于一个客户端来说,如果需要进行写操作,他连上的server,可以是follower或者leader,但不能是observer。假设连上的是一个follower,当client向follower发送一个写命令后,follower会将命令发送给leader。leader会将这个命令发送给所有的follower,将数据写入到每台server中,最终达到最终一致性。那么如何做的呢?
leader会广播给所有的follower让它们写日志,如果拿到的回复是OK的超过了一半,那么就会进行下一步。
广播给所有的follower写命令,将数据写入内存。
zk leader内部存在队列,对于每一个follower都会有一个队列与之对应。队列的先进先出的特性,使得follower从leader拿到的事务id的顺序性有了保证;而队列自身可以保证消息的最终一致性,也就是说如果推送不到会一直努力推送,最终使得消息被推送到再进行下个消息的推送。
如果有一些follower因为如网络因素,在向磁盘中写入日志时没有回复ok,如果总投票超过一半,那么对第二步没有影响。如果是在write时没有回复ok,只要超过一半,其实对后面的其他操作也是没什么影响的,只是连接到这台follower的client拿到的数据可能会是旧的数据,如果有需要可以加sync命令拿到最新的数据。
2、zk选举
zk在leader挂掉后,会有一个短暂的不可用的时间。这段时间用于zk内部选举,只有follower身份的zk节点才能参与选举,obserber是没有选举权力的,这样是为了快速决定出zk leader。
总得来说,选举的原则是,1、要选择事务id最大的,事务id最大,表示数据最完整。2、如果事务id最大的有不止一个,那么在这些节点中选择myid最大的作为leader。
参考文章: