zk使用ZAB(zookeeper atomic broadcase 原子消息广播协议)作为其数据一致性的核心算法。
- 基于此协议,zookeeper实现了一种主备模式的系统架构来保持集群中各副本之间数据的一致性。具体的,zk使用一个单一的主进程来接收并处理客户端的所有事务请求,并采用ZAB的原子广播协议,将服务器数据的状态变更以事务proposal的形式广播到所有的副本进程上。针对客户端的并发请求,能保持较好的一致性。
- ZAB保证一个全局的变更序列被顺序应用,确保请求处理的顺序性
- ZAB协议保证在当前主进程出现崩溃退出或重启等异常情况时,依旧能够正常工作
ZAB协议包括两种基本的模式,分别是崩溃恢复和消息广播。当Leader出现网络中断、崩溃退出与重启等异常情况,ZAB协议就会进入恢复模式并选举产生新的leader服务器,并且集群中过半服务器和新的leader服务器完成状态同步后,就会退出恢复模式。而后进入消息广播模式。
消息广播
针对客户端的事务请求,Leader服务器会为其生成对应的事务Proposal,并将其发送给集群中其余所有的follow机器,follow机器收到事务proposal后,会以事务日志的形式写入到本地磁盘,在写入成功后反馈ack给leader服务器,leader服务器收集follow机器的ack,当过半的机器反馈ack后,即进行事务提交,leader会广播一个Commit消息给所有的follower机器通知进行事务提交,同时leader自身也会完成事务的提交
在广播事务proposal前,Leader服务器会为这个事务分配一个全局唯一单调递增的事务id(zxid),每一个事务按照其zxid的先后顺序来进行排序和处理,以此保证消息严格的因果关系。
崩溃恢复
当leader机器崩溃后,会触发集群的leader选举。ZAB协议确保集群可以快速选举新的leader,一方面让leader自己知道自身已被选为leader,同时让集群的其他机器也能快速感知到选举产生的新leader服务器。
ZAB协议需要处理一下leader崩溃恢复出现的数据不一致情况:
- ZAB协议需要确保那些已经在leader服务器上提交的事务最终被所有服务器提交。假设leader在收到过半服务器ack,将commit消息发送给所有follower机器之前挂了。
- ZAB协议需要确保丢弃那些只在leader服务器上被提出的事务,在leader服务器提出新事务未被其他服务器接收,leader服务器崩溃恢复成follow服务器时,要抛弃未提交的事务
基于上面两种情况处理,ZAB协议涉及的选举算法需要确保提交已经被leader提交的事务proposal,同时丢弃那些已经被跳过的事务。根据事务id的递增姓,即新选举的leader服务器拥有集群中所有机器的最高编号(zxid最大)的事务proposal。以此确保leader具有所有已经被提交的提案。同时便于新leader确认原leader最新提出的事务是无效的以便原leader抛弃未提交的事