介绍
ZooKeeper 是一个典型的发布/订阅模式的分布式数据管理与协调服务。
ZooKeeper 解决了以下问题:
- 高性能使得 ZooKeeper 能够应用于对系统吞吐有明确要求的大型分布式系统;
- 高可用可以解决分布式的单点问题;
- 具有严格的顺序访问控制能力,主要是针对写操作的严格顺序性,使得客户端可以基于 ZooKeeper 来实现一些复杂的同步原语。
数据结构

ZooKeeper 提供基于类似于文件系统的目录节点树方式的数据存储,每个节点叫做ZNode。每一个节点可以通过路径来标识,这是一个共享的内存中的树型结构。
ZNode分为两种类型:
- 短暂/临时(Ephemeral):当客户端和服务端断开连接后,所创建的Znode(节点)会自动删除;
- 持久(Persistent):当客户端和服务端断开连接后,所创建的Znode(节点)不会删除。
ZNode之间的层级关系就像文件系统的目录结构一样,但和传统的磁盘文件系统不同的是全量数据都存储在内存中,以此来实现提高服务器吞吐、减少延迟的目的,从这一点来说应用只应该存储控制信息和配置信息到ZNode,而不应该用它来存储大量数据。
数据节点ZNode
在zk中“节点”分为两类,第一类同样是指构成zk集群的机器,称之为机器节点;
第二类则是指数据模型中的数据节点ZNode。ZK将所有数据存储于内存中,数据模型是一颗ZNode Tree,由斜杠分隔的的路径就是一个ZNode,如/app1/p_1,每个ZNode上都会保存数据内容,还会保存相应属性信息。
ZNode可以分为持久节点和临时节点两类。
- 短暂/临时(Ephemeral):当客户端和服务端断开连接后,所创建的Znode(节点)会自动删除;
- 持久(Persistent):当客户端和服务端断开连接后,所创建的Znode(节点)不会删除,除非主动进行删除操作。
ZK还支持客户端创建节点时指定一个特殊的SEQUENTIAL属性,这个节点被创建的时候ZK会自动在其节点名后面追加上一个整形数字,该数字是一个由服务端维护的自增数字,以此实现创建名称自增的顺序节点。
监听器Watcher
Watcher是ZK中很重要的特性,ZK允许用户在指定节点上注册一些Watcher,在该节点相关特定事件(比如节点添加、删除、子节点变更等)发生时Watcher会监听到,ZK服务端会将事件通知到感兴趣的客户端上去,该机制是ZK实现分布式协调服务的重要特性。
通知的时候服务端只会告诉客户端一个简单的事件(通知状态、事件类型、节点路径)而不包含具体的变化信息(如原始数据及变更后的数据),客户端如要具体信息再次主动去重新获取数据;此外,无论是服务端还是客户端,只要Watcher被触发ZK就会将其删除,因此在Watcher的使用上需要反复注册,这样轻量的设计有效减轻了服务端压力,如果Watcher一直有效,节点更新频繁时服务端会不断向客户端发送通知,对网络及服务端性能影响会非常大。
客户端连接
客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了监听器,这个监听器也是由所连接的 zookeeper 机器来处理。对于写请求,这些请求会同时发给其他 zookeeper 机器并且达成一致后,请求才会返回成功。因此,随着 zookeeper 的集群机器增多,读请求的吞吐会提高但是写请求的吞吐会下降。
有序性是 zookeeper 中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为 zxid(Zookeeper Transaction Id)。而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个 zookeeper 最新的 zxid。
网友评论