Zab 协议

Google提出了中心化组件Chubby—粗粒度锁服务。

通过锁原语为其他系统实现更高级的服务,比如组成员、域名服务和leader选举等等。

Chubby本身也是一个小型的cell,cell内部采用类似于状态机副本形式实现可靠容错。很好的解决了分布式开发的一致性问题;


Yahoo!借鉴Chubby的设计思想开发了Zookeeper,并将其开源。

和Chubby相比,Zookeeper做了很多突破。

不像Chubby的单点服务的结构,zookeeper采用多个server同时处理客户端的请求,异步读同步写,通过primary节点来同步数据的update,这一点大大改善了读服务的性能,当然弱化了客户端与服务器之间的一致性。

另外,zookeeper采用block free的服务接口,采用watch机制的方式异步处理请求结果和指定数据的变更。


zookeeper采用paxos的变种来实现消息传输的一致性。

Zookeeper开发了原子多播协议 Zab 来实现数据的一致性传输。

Zookeeper采用的是primary-backup的结构,primary节点产生non- commutative 事务,通过协议按序的广播到其他backup节点上。在节点无错的情况下,这是非常简单的事情,然而,面对复杂的网络环境,多变的软硬件条件,节点挂掉,重启,数据重复发送,这些异常很常见。Zookeeper如何做到即便是系统出现异常,也能够保证整个系统状态是一致?paxos的变种,Zookeeper的Zab协议很好的保证了这一点。

Zab 协议以epoch的方式执行(相当与序列号),在每个epoch最多只有一个进程多播数据。如果某个进程执行了协议的的第一阶段,那么进程将不再接受之前还没确定提交的epoch的数据。这样一来就保证了在进程在recovery阶段不会出现丢失已提交的数据的情况。在某个epoch下,所有参加这个epoch的进程必须此epoch之前所有已经提交的数据镜像。为了保证一致性,进程在完全恢复之前必须不能广播新的事务。

Zab协议的这几个特点处理了primary异常、新旧primary以及backup节点异常的情况,的确保证了primary进程原子多播的order特性。


整个Zab协议的内容分成三个阶段:Discovery、Synchronization和Broadcast阶段。

Discovery阶段其实是选举leader或者发现leader。

    在这个阶段里,follower会给(可能是)leader的进程(这里的进程可以是多个)发送当前自己epoch的信息CEPOCH;

    如果(可能是)leader进程收到大多数的follower的CEPOCH消息,那么leader就会产生一个新epoch的消息NEWEPOCH,其中包含新的leader,并发送给follower;当follower f收到NEWEPOCH时,f会判断其中epoch是否比当前的大,如果是则反馈信息ACK-E,其中包含f所接受的最大事务编号和历史数据;leader会从这些ACK-E中选出最新的历史数据来初始化它当前的系统状态。这个阶段其实就是paxos的执行过程,由于两个大多数集合的交集肯定不为空,所以不可能一个epoch下会选出两个不同的leader。因此Discovery阶段最后的结果肯定只有一个新leader。

    在整个系统初始的时候,每个节点当前的epoch都为0,这样会给其它节点发送请求,这样有可能会导致paxos死锁,对此,每个zookeeper节点会通过配置获得唯一的id,并根据id的大则优先的原则来推选leader。


Synchronization阶段其实就会状态同步,新leader会将其最新状态通知给所有的follower;follower的到leader的状态后,会和自己的进行比较,从中提前还未提交的数据T,并反馈给leader;leader收到大多数确认反馈时,则发送提交命令commit给这些follower;follower收到commit后提交T中的所有数据。


Broadcast阶段和Synchronization阶段相似,只是这个阶段是对一个请求的提交而不是一个集合的提交。





你可能感兴趣的:(Zab)