ZooKeeper系列文章:http://www.javashuo.com/article/p-waqydwdc-bt.htmlhtml
ZooKeeper是一个开源的为分布式应用提供分布式协调的服务。它公开了一组简单的原语,分布式应用程序能够基于这些原语实现更高级别的服务,包括同步、维护配置、组和命名。它的设计易于编程,它使用一个遵循文件系统中常见的目录树结构的数据模型。它在Java环境中运行,对Java和C都有绑定。node
协调服务是出了名的难。它们特别容易出错,如竞态条件和死锁。ZooKeeper背后的动机是让分布式应用从零开始实现一站式协调服务。数据库
ZooKeeper很简单。经过共享一个相似于标准文件系统结构的层次名称空间,Zookeeper容许分布式进程进行各自的协调。名称空间中包含了注册数据——即所谓的znodes,它们相似于文件和目录。Zookeeper不像文件系统,目的是数据存储,Zookeeper的数据存放在内存中,这意味着zookeeper具备高吞吐量和低延迟的优势。编程
ZooKeeper很是注重高性能、高可用性、严格有序的访问。ZooKeeper的性能方面意味着它能够在大型分布式系统中使用。可靠性方面使它不会出现单点故障。严格有序意味着能够在客户端实现复杂的同步原语。api
ZooKeeper是复制的。与它所协调的分布式进程同样,ZooKeeper自己也打算在一组主机上进行复制。缓存
组成ZooKeeper的每一个server之间都必须互相了解。每一个server都维护状态信息(state)的内存映像,以及持久存储中的事务日志和快照。只要ZooKeeper中的大多数server可用,ZooKeeper服务就可用。session
每一个client链接到ZooKeeper集群中的某个server。客户端会与之创建TCP链接,经过该TCP链接来发送请求、获取响应、获取观察事件(watch events)以及发送心跳。若是TCP链接中断,客户端将链接到另外一个server。分布式
ZooKeeper是有序的。ZooKeeper给每次更新都贴上一个数字,这个数字反映了全部ZooKeeper事务的顺序。后续操做可使用这个顺序来实现高级抽象,例如同步原语。性能
ZooKeeper速度很快,特别是在"以读为主"的工做负载中尤为快速。ZooKeeper应用程序可用在数千台机器上运行,在多读少写(比率在10:1左右)的环境中表现最好。测试
ZooKeeper提供的名称空间很是相似于标准文件系统。名称是由斜线(/)分隔的路径元素序列。在ZooKeeper名称空间中的每个节点都是经过一条路径来标识的。
与标准文件系统不一样的是,ZooKeeper名称空间中的每一个节点(路径)均可以有与之关联的数据,子节点也如此(译注:即节点的路径自身携带数据)。这就像是一个既文件也目录的文件系统。(ZooKeeper的目的是存储协调数据:状态信息、配置、位置信息等,因此每一个节点存储的数据一般都很小,通常都是kb级别的)。咱们使用术语znode来明确说明咱们正在讨论ZooKeeper数据节点。
znode维护一个包含数据更改版本号、ACL更改版本号和时间戳版本号的stat结构,以便可以作缓存验证和协调更新。每当znode的数据发生变化,版本号就会增长。例如,客户端每次检索数据的同时,也会接收数据的版本信息。
名称空间中,每一个znode上存储的数据的读、写操做都是原子性的。读操做会获取与znode关联的全部数据,写操做会替换全部数据。每一个节点都有一个访问控制列表(ACL),限制谁能够作什么。
ZooKeeper也有临时节点(ephemeral nodes)的概念。只要建立这些znode的会话(session)是活动的,这些znode就存在。当会话结束时,znode被删除。当您想要实现[tbd]时,临时节点很是有用。
ZooKeeper支持观察(watch)的概念。客户端能够在znode上设置一个watch。当znode更改时,将触发并删除一个watch。当watch被触发时,客户端会收到一个通知znode已更改的数据包。若是客户端和ZooKeeper server之间的TCP链接中断了,客户端将收到本地通知。这些可用于[tbd]。
ZooKeeper快速又简单。但因为它的目标是做为构建更复杂服务(如同步)的基础,因此它要实现一些保证。包括:
更多信息,以及如何使用它们,请参见[tbd]。
ZooKeeper的一个设计目标是提供很是简单的编程接口。所以,它只支持如下几个操做:
create
:在树中的某个位置建立一个节点。delete
:删除一个节点。exists
:测试一个节点是否存在。get data
:读取节点数据。set data
:向节点中写入数据。get children
:检索某节点的子节点列表。sync
:等待要传播的数据。更深刻内容,以及如何使用它们实现更高级别的操做,请参阅[tbd]。
下图显示了ZooKeeper服务的高层组件。除了request processor,构成ZooKeeper Service的每一个server都复制本身的每一个组件副本。
replicated database是包含整个数据树(data tree)的内存数据库。每次发起的更新都会将其记录到磁盘中的日志,以便之后可以进行恢复(recovery),在更新真正应用到内存数据库以前,还会先将更新序列化到磁盘中。
每一个ZooKeeper server都会为客户端提供服务。客户端链接到一个server来提交request。对于read request,每一个server会从本地database的副本中提供服务。对于write request,这些请求会更改服务状态,它们由协商协议(agreement procotol)来处理。
做为协商协议(agreement procotol)的一部分,全部来自客户端的write request都被转发到一个称为leader的server上。ZooKeeper中的其它server,都称为follower,它们接收来自leader的消息,并传递那些达成一致的消息。消息层(messaging layer)负责在leader故障时选举新的leader,并剩余的follower和新的leader保持同步。
ZooKeeper使用一个自定义的原子消息传递协议。因为该消息层是原子性的,ZooKeeper能够保证本地副本永远不会出现分歧。当leader收到write request时,它会计算当写操做被执行时系统状态,并将其转换为带有该状态的事务。
ZooKeeper的编程接口很简单。但有了它,您能够实现更高级的操做,好比同步原语、组成员关系(group membership)、全部权(ownership)等等。更多信息请参阅[tbd]。
ZooKeeper具备高性能。真的如此吗?雅虎ZooKeeper的开发团队的研究结果已经代表确实如此。(参见下图)。当读操做比写操做更频繁时,ZooKeeper的性能很是高,由于写操做会调用全部节点的状态同步。(协调服务的典型状况就是多读少写)。
注意:在3.2版本中,r/w的性能比3.1版本提升了大约2倍。