ZooKeeper是一个具有高可用性的高性能协调服务。
数据模型
ZooKeeper维护着一个树形层次结构,树中的节点被称为znode。Znode可以用于存储数据,并且有一个与之相关联的ACL(Access Control List访问控制列表)。ZooKeeper被设计用来实现协调服务(这类服务通常使用小数据文件),而不是用于大容量数据存储,因此一个znode能存储的数据被限制在1MB以内。
ZooKeeper的数据访问具有原子性。客户端在读取一个znode的数据时,要么读到所有的数据,要么读操作失败,不会只读到部分数据。同样,一个写操作将替换znode存储的所有数据。ZooKeeper会保证写操作不成功就失败,不会出现部分写之类的情况,也就是不会出现只保存客户端所写部分数据的情况。ZooKeeper不支持添加操作。这些特征都是与HDFS所不同的。HDFS被设计用于大容量数据存储,支持流式数据访问和添加操作。
Znode通过路径被引用。像Unix中的文件系统路径一样,在ZooKeeper中路径被表示成用斜杠分隔的Unicode字符串。与Unix中的文件系统路径不同的是,ZooKeeper中的路径必须是绝对路径,也就是说每条路径必须从一个斜杠字符开始。此外,所有的路径表示必须是规范的,即每条路径只有唯一的一种表示方式,不支持路径解析。例如,在Unix中,一个具有路径/a/b的文件也可以表示为/a/./b,原因在于“.”在Unix的路径中表示当前目录。在ZooKeeper中,“.”不具有这种特殊含义,这样表示的路径名是不合法的。
在ZooKeeper中,路径由Unicode字符串构成,并且有一些限制。字符串“zookeeper”是一个保留词,不能将它作为路径表示中的一部分。ZooKeeper中使用/zookeeper子树来保存管理信息,例如关于配额信息。
1. 短暂znode
znode有两种类型:短暂的和持久的。Znode的类型在创建时被确定并且之后不能再修改。在创建短暂znode的客户端会话结束时,ZooKeeper会将该短暂znode删除。相比之下,持久znode不依赖于客户端会话,只有当客户端(不一定是创建它的那个客户端)明确要删除该持久化znode时才会被删除。短暂znode不可以有子节点,即使是短暂子节点。
虽然每个短暂znode都会被绑定到一个客户端会话,但它们对所有的客户端还是可见的(还要符合其ACL的定义)。
对于那些需要知道特定时刻有哪些分布式资源可用的应用来说,使用短暂znode是一种理想的选择。
2. 顺序号
顺序(sequential)znode是指名称中包含ZooKeeper指定顺序号的znode。如果在创建znode时设置了顺序标识,那么该znode名称之后便会附加一个值,这个值是由一个单调递增的计数器(由父节点维护)所添加的。
在一个分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端就可以通过顺序号来推断事件的顺序。
3. 观察
znode以某种方式发生变化时,“观察”(watch)机制可以让客户端得到通知。可以针对ZooKeeper服务的操作来设置观察,该服务的其他操作可以出发观察。例如,客户端可以对一个znode调用exists操作,同时设定一个观察。如果这个znode不存在,则客户端所调用的exists操作将返回false。如果一段时间之后,另外一个客户端创建了这个znode,则这个观察会被触发,通知前一个客户端这个znode被创建。
观察只能被触发一次(连接事件的回调除外)。为了能够多次收到通知,客户端需要重新注册所需要的观察。