ZooKeeper开发手册中文翻译


摘要 自己翻译的ZooKeeper官方文档,需要的人可以参考一下,有翻译错误还请指正。

目录

ZooKeeper的数据模型
ZNodes
ZooKeeper中的时间
ZooKeeper状态结构(Stat Structure)
ZooKeeper Sessions
ZooKeeper Watches
使用ACL控制ZooKeeper访问权限
ACL权限
内建ACL模式
ZooKeeper C client API
插件式ZooKeeper认证
一致性保证
编程接口
常见问题和故障

翻译:steve sun 博客地址:http://sundiontheway.github.io/blog

--------------------------------------分割线 --------------------------------------

ZooKeeper集群配置

使用ZooKeeper实现分布式共享锁

分布式服务框架 ZooKeeper -- 管理分布式环境中的数据

ZooKeeper集群环境搭建实践

ZooKeeper服务器集群环境配置实测

ZooKeeper集群安装

--------------------------------------分割线 --------------------------------------

本文假设你已经具有一定分布式计算的基础知识。你将在第一部分看到以下内容:

  • ZooKeeper数据模型

  • ZooKeeper Sessions

  • ZooKeeper Watches

  • 一致性保证(Consistency Guarantees)

接下来的4小节讲述了程序开发的实际应用:

  • 创建模块——ZooKeeper操作指引

  • 编程语言接口

  • 简单示例演示程序的结构

  • 常见问题和故障

本文的附录中包含和ZooKeeper相关的有用信息。

ZooKeeper的数据模型

ZooKeeper有一个类似分布式文件系统的命名体系。区别在于Zookeeper每个一个节点或子节点都可以拥有数据。节点路径是一个由斜线分开的绝对路径,注意没有相对路径。只要满足下面要求的unicode字符都可以作为节点路径:

  • 空字符不能出现在路径名

  • 不能出现以下字符: \u0001 - \u0019 and \u007F - \u009F

  • 以下字符不允许使用: \ud800 -uF8FFF, \uFFF0-uFFFF, \uXFFFE - \uXFFFF (where X is a digit 1 - E), \uF0000 - \uFFFFF

  • 字符"."可以作为一个名字的一部分, 但是"."和".."不能单独作为相对路径使用, 以下用法都是无效的: "/a/b/./c"或者"/a/b/../c"

  • "zookeeper"为保留字符

ZNodes

ZooKeeper树结构中的节点被称为znode。各个znode维护着一组用来标记数据和访问权限发生变化的版本号。这些版本号组成的状态结构 具有时间戳。Zookeeper使用版本号和时间戳来验证缓存状态,调整更新。 每次znode中的数据发生变化,znode的版本号增加。例如,每当一个客户端恢复数据时,它就接收这个版本的数据,而当一个客户端提交了更新或删除记 录,它必须同时提供这个znode当前正在发生变化的数据的版本。如果这个版本和目前真实的版本不匹配,则提交无效。 __提示,在分布式程序中,一个字节点可以代表一个通用的主机,服务器,集群中的一员,客户端程序等。但是在Zookeeper中,znode代表数据节 点,Servers代表组成了Zookeeper服务的机器; quorum peers refer to the servers that  make up an ensemble; 客户端代表任何使用ZooKeeper服务的主机或程序。

znode作为对程序开发来说最重要的信息,有几个特性需要特别关注下:

Watches 客户端可以在znode上设置Watch。znode发生的变化会触发watch然后清除watch。当一个watch被触发,Zookeeper给客户端发送一个通知。更多关于watch的内容请查看ZooKeeper Watches一节。

数据存取 命名空间中每个znode中的数据读写是原子操作。读操作读取znode中的所有数据位,写操作则替换所有数据。每个节点都有一个访问权限控制表 (ACL)来标记谁可以做什么。 zookeeper不是设计成普通的数据库或大型对象存储的。它是用来管理coordination data。coordination  data包括配置文件、状态信息、rendezvous等。这些数据结构的一个共同特点就是相对较小——以千字节为准。Zookeeper的客户端和服务 会检查确保每个znode上的数据小于1M,实际平均数据要远远小于1M。 大规模数据的操作会引发一些潜在的问题并且延长在网络和介质之间传输的时间。如果确实需要大型数据的存储,那么可以采用如NFS或HDFS之类的大型数据 存储系统,亦或是在zookeeper中存储指向存储位置的指针。

临时节点(Ephemeral Nodes) zookeeper还有临时节点的概念,这些节点的生命周期依赖于创建它们的session是否活跃。session结束时节点即被销毁。也由于这种特性,临时节点不允许有子节点。

序列节点——命名不唯一 当你创建节点的时候,你会需要zookeeper提供一组单调递增的计数来作为路径结尾。这个计数对父znode是唯一的。用%010d的格式——用0来填充的10位数(计数如此命名是为了简单排序)。例如"0000000001",注意计数器是有符号整型,超过表示范围会溢出。

ZooKeeper中的时间

zookeeper有很多记录时间的方式:

  • Zxid(ZooKeeper Transaction Id): zookeeper每次发生改动都会增加zxid,zxid越大,发生的时间越靠后。

  • Version numbers: 对znode的改动会增加版本号。版本号包括version (znode上数据的修改数), cversion (znode的子节点的修改数), aversion (znode上ACL(权限)的修改数)。

  • Ticks : 多个server构成zookeeper服务时,各个server用ticks来标记如状态上报、连接超时等事件。ticks  time还间接反映了session超时的最小值(两次tick time);如果客户端请求的最小session  timeout低于这个最小值,服务端会通知客户端最小超时置为这个最小值。

  • Real time : 除了每次znode创建或改动时候将时间戳记录到状态结构中外,zookeeper不使用时钟时间。

ZooKeeper状态结构(Stat Structure)

存在于znode中的状态结构,由以下各个部分组成:

  • czxid - znode创建产生的zxid

  • mzxid - znode最后一次修改的zxid

  • ctime - znode创建的时间的绝对毫秒数

  • mtime - znode最后一次修改的绝对毫秒数

  • version - znode上数据的修改数

  • cversion - 子节点修改数

  • aversion - znode的ACL修改数

  • ephemeralOwner - 临时节点的所有者的session id。如果此节点非临时节点,该值为0

  • dataLength - znode的数据长度

  • numChildren - znode子节点数

ZooKeeper Sessions

客户端通过创建一个handle和服务端建立session连接。一旦创建完成,handle就进入了CONNECTING状态,客户端库尝试连接一台构成zookeeper的server,届时进入CONNECTED状态。通常情况下操作会介于这两种状态之间。 一旦出现了不可恢复的错误:如session中止,鉴权失败或者应用直接结束handle,则handle会进入到CLOSED状态。下图是客户端的状态转换图:

状态转换图

应用在创建客户端session时必须提供一串逗号分隔的主机号:端口号,每对主机端口号对应一个ZooKeeper的 server(如:"127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002"),客户端库会尝试连接任意一台服务 器,如果连接失败或是客户端主动断开连接,客户端会自动继续与下一台服务器连接,直到连接成功。

3.2.0版本新增内容:  一个新的操作“chroot”可以添加在连接字符串的尾部,用来指明客户端命令运行的根目录地址。类似unix的chroot命令,例如: "127.0.0.1:4545/app/a" or  "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a",说明客户端会以"/app/a"为根目 录,所有路径都相对于根目录来设置,如"/foo/bar"的操作会运行在"/app/a/foo/bar"。 这一特性在多用户环境下非常好用,每个使用zookeeper服务的用户可以设置不同的根目录。

当客户端获得和zookeeper服务连接的handle时,zookeeper会创建一个Zookeeper  session分配给客户端,用一个64-bit数字表示。一旦客户端连接了其他服务器,客户端必须把这个session  id也作为连接握手的一部分发送。出于安全目的,zookeeper给session id创建一个密码,任何zookeeper服务器都可以验证密码。 当客户端创建session时密码和session id一起发送到客户端来,当客户端重新连接其他服务器时,同时要发送密码和session id。

zookeeper客户端库里有一个创建zookeeper session的参数,叫做session  timeout(超时),用毫秒表示。客户端发送请求超时,服务端在超时范围内响应客户端。session超时最小为2个ticktime,最大为20个 ticktime。zookeeper客户端API可以协调超时时间。 当客户端和zookeeper服务器集群断开时,它会搜索session创建时的服务器列表。最后,当至少一个服务器和客户端重新建立连 接,session或被重新置为"connected"状态(超时时间内重新连接),或被置为"expired(过期)"状态(超出超时时间)。不建议在 断开连接后重新创建session。ZK客户端库会帮你重新连接。特别地,我们将启发式学习模式植入客户的库中来处理类似“羊群效应”等问题。只有当你的 session过期时才重新创建(托管的)。 session过期的状态转换图示例同过期session的watcher:

  1. 'connected' : session正确创建,客户端和服务集群正常连接

  2. .... 客户端从服务器集群断开

  3. 'disconnected' : 客户端失去和服务器集群的连接

  4. .... 过了一段时间, 超过了集群判定session过期的超时时间, 客户端并没有发觉自己和服务集群断开了连接

  5. .... 又过一段时间, 客户端恢复了同集群的网络连接

  6. 'expired' : 最终客户端重新连上集群,然后被通知已经到期

另一个session建立时zookeeper需要的参数是默认watcher(监视者)。在客户端发生任何变化时,watcher都会发出通知。 例如客户端失去和服务器的连接、客户端session到期等。watcher默认的初始状态是disconnected。(也就是说任何状态改变事件都由 客户端库发送到watcher)。当新建一个连接时,第一个发送给watcher的事件通常就是session连接事件。

客户端发送请求会使session保持活动状态。客户端会发送ping包(译者注:心跳包)以保持session不会超时。Ping包不仅让服务端 知道客户端仍然活动,而且让客户端也知道和服务端的连接没有中断。Ping包发送时间正好可以判断是否连接中断或是重新启动一个新的服务器连接。

和服务器的连接建立成功,当一个同步或异步操作执行后,有两种情况会让客户端库判断失去连接:

  1. 应用在session上请求了一个已经失效的操作

  2. zookeeper服务器有一个等待中的操作时,客户端会从那台服务器断开连接。即服务器有等待的异步调用。

3.2.0版本新增内容 —— SessionMovedException  一个客户端无法查看的内部异常SessionMovedException。这个异常发生在服务端收到一个请求,这个请求的session已经在另一个服 务器上重新连接。发生这种情况的原因通常是客户端发送完请求后,由于网络延时,客户端超时重新和其他服务器建立连接,当请求包到达第一台服务器时,服务器 发现session已经移除并关闭了和客户端的连接。客户端一般不用理会这个问题,但是有一种情况值得注意,当两台客户端使用事先存储的session  id和密码试图创建同一个连接时,第一台客户端重建连接,第二台则会被中断。

更多详情见请继续阅读下一页的精彩内容:

  • 1
  • 2
  • 下一页

相关内容