0.简介
本文档是一篇利用ZooKeeper来协调分布式应用程序的开发指南。它包含基础概念和实战信息。
本指南的前四部分介绍了各种ZooKeeper概念。这些对于理解ZooKeeper如何工作以及如何使用它们都是必要的。它不包含源代码,但它确实熟悉与分布式计算相关的问题。
第一组中的部分是:
-
The ZooKeeper Data Model 数据模型
-
ZooKeeper Sessions 会话
-
ZooKeeper Watches
-
Consistency Guarantees
接下来的四节提供了实用的编程信息:
-
Building Blocks: A Guide to ZooKeeper Operations 基本操作
-
Bindings
-
Program Structure, with Simple Example [tbd] 简单编程示例
-
Gotchas: Common Problems and Troubleshooting 常见问题和解决方案
本文档中的大部分信息都是互相独立的。但在开始第一个ZooKeeper应用程序之前,您应该至少阅读ZooKeeper数据模型和ZooKeeper基本操作的章节。此外,简单编程示例[tbd]有助于理解ZooKeeper客户端应用程序的基本结构。
1.ZooKeeper数据模型
ZooKeeper有一个分层命名空间,很像分布式文件系统。唯一的区别是命名空间中的每个节点都可以包含与之关联的数据以及子节点,这就像一个允许文件同时也是目录的文件系统。节点的路径始终表示为斜线分隔的绝对路径,没有相对路径。路径有一定的命名规范:
- 不能包含空字符
- 不能包含 \u0001 - \u0019 和 \u007F - \u009F 范围的不可打印的字符
- 不能包含\ud800 -uF8FFF, \uFFF0-uFFFF, \uXFFFE - \uXFFFF (where X is a digit 1 - E), \uF0000 - \uFFFFF
- 可以包含.和.. 因为不支持相对路径,所以这两个没有特殊意义
- zookeeper时保留关键字,不能使用
1.1 ZNodes
ZooKeeper树中的每个节点都称为znode。 Znodes维护一个stat结构,包括数据修改、acl修改的版本号,还有时间戳。版本号与时间戳共同作用使ZooKeeper能够验证缓存并协调更新。每当znode的数据修改时,版本号都会增加;当客户端检索数据时,它也会接收数据的版本;当客户端执行更新或删除时,它必须提供正在更改的znode的数据版本,如果它提供的版本与实际版本的数据不匹配,则更新将失败。
在分布式应用程序工程中,单词node可以指通用主机,服务器,集合成员,客户端进程等。在ZooKeeper文档中,znodes指的是数据节点。服务器指的是构成ZooKeeper服务的机器;quorum peers是指构成整体的服务器; client指的是使用ZooKeeper服务的任何主机或进程。
Znodes是程序员访问的主要实体:它们有一下几个特征:
Watches :客户端可以在znodes上设置watch监控。znode的更改会触发watch并清除watch。当触发watch时,ZooKeeper会向客户端发送通知。
Data Access:存储在命名空间中每个znode的数据以原子方式读取和写入。每次读取都是获取与znode关联的所有数据字节,写入也是只能替换所有数据。每个节点都有一个访问控制列表(ACL,Access Control List),限制谁可以做什么。
ZooKeeper并非设计为通用数据库或大型对象库。相反,它管理协调数据。这些数据可以是配置,状态信息,会话等形式。这些形式的协调数据的共同特性是它们相对较小:以KB千字节为单位。 ZooKeeper客户端和服务器实现具有相关检查以确保znode的数据少于1M,且数据应远小于平均数据。在相对较大的数据上操作将导致某些操作比其他操作花费更多的时间并且将影响某些操作的延迟,因为通过网络将更多数据移动到存储介质上需要额外的时间。如果需要大数据存储,处理此类数据的通常模式是将其存储在大容量存储系统(如NFS或HDFS)上,并在ZooKeeper中存储指向存储位置的指针。
Ephemeral Nodes临时节点
ZooKeeper也有临时节点的概念。只要创建znode的会话处于活动状态,就会存在这些临时znode,会话结束时,就被删除。由于这种行为,临时znodes不允许有孩子。
Sequence Nodes -- Unique Naming 序列节点
创建znode时,您还可以请求ZooKeeper在路径末尾附加一个单调递增的计数器。此计数器对于父znode是唯一的。计数器的格式为%010d (即10位数不足以0填充),如“<path> 0000000001”。注意:用于存储下一个序列号的计数器是由父节点维护的signed int(4字节),当递增超过2147483647时,计数器将溢出(产生名称“<path> -2147483647”)。
1.2 ZooKeeper的时间
ZooKeeper以多种方式跟踪时间:
- Zxid:对ZooKeeper状态的每次更改都会盖个zxid(ZooKeeper Transaction Id)戳。这标识了ZooKeeper所有更改的时序关系。每个更改都将具有唯一的zxid,如果zxid1小于zxid2,则zxid1发生在zxid2之前。
- Version numbers版本号:对节点的每次更改都将导致该节点的某个版本号增加。三个版本号分别是version版本(znode数据的更改次数),cversion(znode子项的更改次数)和aversion(znode的ACL更改次数)。
- Ticks滴答:当使用多服务器ZooKeeper时,服务器使用Ticks来定义事件的时间,例如状态上载,会话超时,对等体之间的连接超时等。滴答时间仅通过最小会话超时时间(滴答时间的2倍)间接暴露;如果客户端请求的会话超时小于最小会话超时,则服务器将告诉客户端会话超时实际上是最小会话超时。
- Real time:除了在znode创建和znode修改时将时间戳放入stat结构之外,ZooKeeper根本不使用真实时间或时钟时间。
1.3 Stat Structure
ZooKeeper中每个znode的Stat结构由以下字段组成:
- czxid :导致创建此znode的更改的zxid。
- mzxid: 最后修改此znode的更改的zxid。
- ctime :创建此znode时从纪元开始的时间(以毫秒为单位)。
- mtime: 上次修改此znode时的时间(以毫秒为单位)。
- version:此znode数据的更改次数。
- cversion :此znode的子项的更改数。
- aversion: 此znode的ACL更改次数。
- ephemeralOwner: 如果znode是临时节点,存的是znode的所有者的会话ID。如果它不是短暂的节点,则它将为零。
- dataLength: 此znode的数据字段的长度。
- numChildren:的 这个znode的子节点数。