ZooKeeper架构设计及其应用要点

问题导读:

1.ZooKeeper的数据模型是什么 ?
2.ZooKeeper应用有哪些陷阱 ?
3.每一个节点(ZNode)中存储的是什么?
4.一个ZNode维护了一个状态结构都包含了什么?
5.ZNode组成结构是什么?
6.Watches的机制是什么?
7.ZooKeeper内置了哪4种方式实现ACL?






前言php

ZooKeeper 是一个开源的分布式服务框架,它是ApacheHadoop 项目的一个子项目,主要用来解决分布式应用场景中存在的一些问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置管理等,它支持Standalone 模式和分布式模式,在分布式模式下,可以为分布式应用提供高性能和可靠地协调服务,并且使用ZooKeeper 能够大大简化分布式协调服务的实现,为开发分布式应用极大地下降了成本。



整体架构
ZooKeeper 分布式协调服务框架的整体架构,如图所示:
<ignore_js_op> 




ZooKeeper 集群由一组Server 节点组成,这一组Server 节点中存在一个角色为Leader 的节点,其余节点都为Follower 。当客户端Client 链接到ZooKeeper 集群,而且执行写请求时,这些请求会被发送到Leader 节点上,而后Leader 节点上数据变动会同步到集群中其余的Follower 节点。
Leader 节点在接收到数据变动请求后,首先将变动写入本地磁盘,以做恢复之用。当全部的写请求持久化到磁盘之后,才会将变动应用到内存中。
ZooKeeper 使用了一种自定义的原子消息协议,在消息层的这种原子特性,保证了整个协调系统中的节点数据或状态的一致性。Follower 基于这种消息协议可以保证本地的ZooKeeper 数据与Leader 节点同步,而后基于本地的存储来独立地对外提供服务。
当一个Leader 节点发生故障失效时,失败故障是快速响应的,消息层负责从新选择一个Leader ,继续做为协调服务集群的中心,处理客户端写请求,并将ZooKeeper 协调系统的数据变动同步(广播)到其余的Follower 节点。

 

设计要点
ZooKeeper 是基于以下4 个目标来进行权衡和设计的,咱们从设计及其特性的角度来详细说明:

 

 
简单
分布式应用中的各个进程能够经过ZooKeeper 的命名空间(Namespace )来进行协调,这个命名空间是共享的、具备层次结构的,更重要的是它的结构足够简单,像咱们平时接触到的文件系统的目录结构同样容易理解,如图所示:
<ignore_js_op>



 
ZooKeeper 中每一个命名空间(Namespace )被称为ZNode ,你能够这样理解,每一个ZNode 包含一个路径和与之相关的元数据,以及继承自该节点的孩子列表。与传统文件系统不一样的是,ZooKeeper 中的数据保存在内存中,实现了分布式同步服务的高吞吐和低延迟。
在上图示例的ZooKeeper 的数据模型中,有以下要点:

 

每一个节点(ZNode )中存储的是同步相关的数据(这是ZooKeeper 设计的初衷,数据量很小,大概B KB 量级),例如状态信息、配置内容、位置信息等。
一个ZNode 维护了一个状态结构,该结构包括:版本号、ACL 变动、时间戳。每次ZNode 数据发生变化,版本号都会递增,这样客户端的读请求能够基于版本号来检索状态相关数据。
每一个ZNode 都有一个ACL ,用来限制是否能够访问该ZNode
在一个命名空间中,对ZNode 上存储的数据执行读和写请求操做都是原子的。
客户端能够在一个ZNode 上设置一个监视器(Watch ),若是该ZNode 数据发生变动,ZooKeeper 会通知客户端,从而触发监视器中实现的逻辑的执行。
每一个客户端ZooKeeper 链接,便创建了一次会话(Session ),会话过程当中,可能发生CONNECTING CONNECTED CLOSED 三种状态。
ZooKeeper 支持临时节点(EphemeralNodes )的概念,它是与ZooKeeper 中的会话(Session )相关的,若是链接断开,则该节点被删除。
 
冗余
ZooKeeper 被设计为复制集群架构,每一个节点的数据均可以在集群中复制传播,使集群中的每一个节点数据同步一致,从而达到服务的可靠性和可用性。前面说到,ZooKeeper 将数据放在内存中来提升性能,为了不发生单点故障(SPOF ),支持数据的复制来达到冗余存储,这是必不可少的。

 

 
有序
ZooKeeper 使用时间戳来记录致使状态变动的事务性操做,也就是说,一组事务经过时间戳来保证有序性。基于这一特性。ZooKeeper 能够实现更加高级的抽象操做,如同步等。

 

 
快速
ZooKeeper 包括读写两种操做,基于ZooKeeper 的分布式应用,若是是读多写少的应用场景(读写比例大约是10:1 ),那么读性能更可以体现出高效。



数据模型
ZooKeeper 有一个分层的命名空间,结构相似文件系统的目录结构,很是简单而直观。其中,ZNode 是最重要的概念,前面咱们已经描述过。另外,有ZNode 有关的还包括Watches ACL 、临时节点、序列节点(Sequence Node )。



ZNode 结构
ZooKeeper 中使用Zxid ZooKeeperTransaction Id )来表示每次节点数据变动,一个Zxid 与一个时间戳对应,因此多个不一样的变动对应的事务是有序的。下面是ZNode 的组成结构,引用文档以下所示:

 

czxid – The zxid of the change that causedthis znode to be created.
mzxid – The zxid of the change that lastmodified this znode.
ctime – The time in milliseconds from epochwhen this znode was created.
mtime – The time in milliseconds from epochwhen this znode was last modified.
version – The number of changes to the dataof this znode.
cversion – The number of changes to thechildren of this znode.
aversion – The number of changes to the ACLof this znode.
ephemeralOwner – The session id of theowner of this znode if the znode is an ephemeral node. If it is not anephemeral node, it will be zero.
dataLength – The length of the data fieldof this znode.
numChildren – The number of children ofthis znode.



Watches (监视)
ZooKeeper 中的Watch 是只能触发一次。也就是说,若是客户端在指定的ZNode 设置了Watch ,若是该ZNode 数据发生变动,ZooKeeper 会发送一个变动通知给客户端,同时触发设置的Watch 事件。若是ZNode 数据又发生了变动,客户端在收到第一次通知后没有从新设置该ZNode Watch ,则ZooKeeper 就不会发送一个变动通知给客户端。
ZooKeeper 异步通知设置Watch 的客户端。可是ZooKeeper 可以保证在ZNode 的变动生效以后才会异步地通知客户端,而后客户端才可以看到ZNode 的数据变动。因为网络延迟,多个客户端可能会在不一样的时间看到ZNode 数据的变动,可是看到变动的顺序是可以保证有序一致的。
ZNode 能够设置两类Watch ,一个是DataWatches (该ZNode 的数据变动致使触发Watch 事件),另外一个是Child Watches (该ZNode 的孩子节点发生变动致使触发Watch 事件)。调用getData() exists()  方法能够设置Data Watches ,调用getChildren() 方法能够设置Child Watches 。调用setData() 方法触发在该ZNode 的注册的Data Watches 。调用create() 方法建立一个ZNode ,将触发该ZNode Data Watches ;调用create() 方法建立ZNode 的孩子节点,则触发ZNode Child Watches 。调用delete() 方法删除ZNode ,则同时触发Data Watches Child Watches ,若是该被删除的ZNode 还有父节点,则父节点触发一个Child Watches
另外,若是客户端与ZooKeeper Server 断开链接,客户端就没法触发Watches ,除非再次与ZooKeeper Server 创建链接。



Sequence Nodes (序列节点)
在建立ZNode 的时候,能够请求ZooKeeper 生成序列,以路径名为前缀,计数器紧接在路径名后面,例如,会生成相似以下形式序列
qn-0000000001, qn-0000000002,qn-0000000003, qn-0000000004, qn-0000000005, qn-0000000006, qn-0000000007
对于ZNode 的父节点来讲,序列中的每一个计数器字符串都是惟一的,最大值为2147483647



ACLs (访问控制列表)
ACL 能够控制访问ZooKeeper 的节点,只能应用于特定的ZNode 上,而不能应用于该ZNode 的全部孩子节点上。它主要有以下五种权限:

 

CREATE  容许建立Child Nodes
READ  容许获取ZNode 的数据,以及该节点的孩子列表
WRITE  能够修改ZNode 的数据
DELETE  能够删除一个孩子节点
ADMIN  能够设置权限

 

ZooKeeper 内置了4 种方式实现ACL

 

world  一个单独的ID ,表示任何人均可以访问
auth  不使用ID ,只有认证的用户能够访问
digest  使用username:password 生成MD5 哈希值做为认证ID
ip  使用客户端主机IP 地址来进行认证

 

ZooKeeper Session
当客户端链接到ZooKeeper 集群时,创建了会话。会话过程当中的状态变迁,如图所示:
<ignore_js_op>



创建链接过程当中,会话状态为CONNECTING ;当链接创建成功后,会话状态变为CONNECTED 。会话过程当中,若是正常的话,会话的状态只能是CONNECTING CONNECTED 两者之一。若是在会话过程当中链接断开,则变为CLOSED 状态。



应用陷阱
并不是任何分布式应用都适合使用ZooKeeper 来构建协调服务,咱们根据ZooKeeper 提供的文档,给出哪些状况下使用会出现问题,又是如何应对这种问题的。 总结以下:

 

 
丢失ZNode 上的变动通知
客户端链接到ZooKeeper Server 之后,会维护一个TCP 链接。在CONNECTED 状态下,客户端设置了某个ZNode Watch 监听器,能够收到来自该节点变动的通知(后续会触发必定的逻辑执行流程)。可是,若是因为网络异常,客户端断开了与ZooKeeper Server 的链接,在断开的过程当中,是没法收到ZooKeeper ZNode 上发送的节点数据变动通知的。
因此,若是使用ZooKeeper Watch ,必需要寻找保持CONNECTED Watch ,才能保证不会丢失该Watch 监控的ZNode 上的数据变动通知。

 

 
无效ZooKeeper 集群节点列表
ZooKeeper 集群交互时,通常状况下客户端会持有一个ZooKeeper 集群节点的列表,或者列表的子集,那么会存在以下两种状况:
一种状况是,若是客户端持有的列表或者列表子集,其中节点都处于Active 状态,可以提供协调服务,那么客户端访问ZooKeeper 集群没有任何问题。
另外一种状况,客户端持有ZooKeeper 集群节点列表或列表子集,若是列表中的某些节点由于故障退出了集群,若是客户端再次链接这一类失效的节点,就没法获取服务。
因此,咱们在应用中使用ZooKeeper 集群时,必定要明确这一点,或者跳过无效的节点,或者从新寻找有效的节点继续业务处理,或者检查ZooKeeper 集群,使整个集群恢复正常。



 
配置致使的性能问题
若是设置Java 堆内存(Heap )不合理,会致使ZooKeeper 内存不足,会在内存与文件系统之间进行数据交换,致使ZooKeeper 的性能极大地降低,从而可能会影响应用程序。
为了不Swapping 问题的出现,主要考虑设置足够的Java 堆内存,同时减小被操做系统和Cache 使用的内存,尽可能避免在内存与文件系统之间发生数据交换,或者能够将交换限制在必定的范围以内。

 

 
事务日志存储设备性能
ZooKeeper 会同步事务到存储设备,若是存储设备不是专用的,而是和其余I/O 密集型应用共享同一磁盘,会致使ZooKeeper 的效率。由于客户端请求ZNode 数据变动而发生的事务,ZooKeeper 会在响应以前将事务日志写入存储设备,若是存储设备是专用的,那么整个服务以致外部应用都会得到极大地性能提高。



ZNode 存储大量数据致使性能问题
ZooKeeper 的设计初衷是,每一个ZNode 只存放少许的同步数据,若是存储了大量数据,致使ZooKeeper 每次节点发生变动时须要将事务写入存储设备,同时还要在集群内部复制传播,这将致使不可避免的延迟和性能问题。
因此,若是须要与大量的数据相关,能够将大量数据存储在其余设备中,而只是在ZooKeeper 存储一个简单的映射,如指针、引用等等。

 文章转自:http://www.aboutyun.com/thread-7731-1-1.htmlhtml

相关文章
相关标签/搜索