1. Zab介绍



ZooKeeper服务的内部通信,是基于Zab协议,即ZooKeeper Atomic Broadcast协议。原子广播(AB)是分布式计算普遍使用的原语。本质上说,ZooKeeper服务是基于复制分发的。它需要半数以上的服务器能正常工作。崩溃的服务器能恢复并且重新加入集群。ZooKeeper采用主备方式来维护被复制状态的一致性。在ZooKeeper中,leader接受所有客户的请求并加以执行,然后将增量的状态变化,以事务的方式通过Zab复制到所有的followers。一旦leader崩溃,在进行常规操作之前,必须执行一套恢复协议,来a). 协调各followers达到一致状态,b). 选举出新的leader。为了选举出leader,新的leader必须得到多数支持(quorum)。由于zookeeper server随时都可能崩溃或恢复,随时间流逝,同一个进程可能好几次成为leader。为了能区分随时间变化的不同的leader实例,ZooKeeper为每一个leader都分配一个实例值。一个leader实例值最多能映射到一个进程。


对Zab设计而言很关键的一点是,对于每个状态变化的观察,都是基于上一个状态的增量变化。这也就意味着对于状态变化,必须依赖于其更新的次序。状态改变过程是不能乱序的。只要增量的发送是有序的,状态的更新便是幂等的,即使某个增量变化被反复执行多次。因此,对于消息系统而言,保证at-least once语义已经足够,以此来简化整个Zab的实现。


Zab是Zookeeper核心的重要组件,因此必须高效运行。ZooKeeper被设计成能支持高吞吐量、低时延的系统。应用能广泛地在集群环境下使用Zookeeper,能接受来自不同数据中心大量的客户端连接。


在设计zookeeper过程中,我们发现很难在隔离的环境下解释清楚原子广播,必定要提及必须满足的应用的需求和目标。在解释原子广播必须涉及应用,这导致了不同的协议元素,甚至是一些有意思的优化。


1.1 Multiple outstanding transactions



在设计中,我们让zookeeper能支持multiple outstanding transactions,即一个zookeeper的客户端能以FIFO次序,并发地提交一组事务操作。传统的协议,如Paxos,并不直接支持这样的特性。如果leader每次提交单个事务,则事务之间的次序将不被保证,在某些情况下,这是不可接受的。Paxos能采取的一个已知的方案,是把多个事务打包成一个提议请求,每次最多提交一个提议而不能并发。这样的设计,会导致吞吐或时延受到影响,这取决于batch size的选择。


1.2 有效恢复(Efficient recovery)



一个重要的设计目标是能够从leader崩溃的情况下快速恢复。为了快速恢复,ZooKeeper使用了事物标识规划(transaction identification scheme),以事务的编号这样简单的方式,来帮助新的leader决定如何恢复状态。在这个事物标识规划中,事物标识以以下两个值组成,实例编号值,以及该事务在该实例中以leader角色广播事物的次序号。在这种规划下,那些已接受最高识别号的实例,才可能需要将相应的事务拷贝到新的leader。没有其他需要恢复的事务了。这就意味了,新的leader只需简单收集其他实例的最高事物标识,就知道需要恢复那些事务了。


然而,这种恢复方式在Paxos下是行不通的。收集每个实例的最大事务标识号,不足以解决快速恢复问题。这是因为,即使序列号相同,不同实例可能会接受不同的值。这导致了必须执行Paxos的Phase I过程,来收集新leader之前不了解的所有的序列号。


1.3 总结(Summary of contributions)

Zab是针对主备系统(primary-backup systems)设计的高性能原子广播(atomic broadcast)协议。同之前的其他原子广播协议进行比较,Zab满足一组不同的纠错属性。特别的,Zab提出了叫主次序(primary order)的属性,这对于主备系统非常重要。它能支持正确的状态更新次序,即使随时间流逝不同进程变成leader,同时支持Multiple outstanding transactions。主次序和因果次序(causal order)是不同的,这在随后章节会讲到。Zab是基于主次序的原子广播。最后,ZooKeeper的事务标识规则,使得ZooKeeper较其他经典算法如Paxos,在恢复上更快速。




Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐