Contents
  1. 1. ZooKeeper数据模型
  2. 2. ZNodes
    1. 2.1. Watch
    2. 2.2. 数据存取Data Access
    3. 2.3. 瞬时节点Ephemeral Nodes
    4. 2.4. 序列节点Sequence Nodes
  3. 3. ZooKeeper中的时间。
    1. 3.1. Zxid
    2. 3.2. 版本号Version numbers
  4. 4. 计时Ticks
    1. 4.1. 时钟时间Real time
    2. 4.2. 状态结构Stat Structure
  5. 5. 会话ZooKeeper Sessions
  6. 6. 监听/ZooKeeper Watches
    1. 6.1. One-time trigger
    2. 6.2. Sent to the client
  7. 7. watch对象
    1. 7.1. Watch有哪些保证
    2. 7.2. 关于Watch的须知

ZooKeeper数据模型

  ZooKeeper拥有一个层级结构的目录空间,非常类似分布式文件系统,唯一的不同是每个node可同时拥有数据和子node,即文件同时也是目录。只使用绝对路径,总的来说任何Unicode字符都可以作为路径的一部分,但遵循以下约束:

null(\u0000)不能用在path中,因为在C中会导致Binding异常。

以下字符因为不能很好显示或易让人迷惑,不可用在path中:\u0001 - \u0019 and \u007F - \u009F.

以下字符也不允许使用: \ud800 -uF8FFF, \uFFF0-uFFFF, \uXFFFE - \uXFFFF (X 代表 1 - E), \uF0000 - \uFFFFF.

.和..可用,但不能单独用来表示node, 亦即/a/b/./c” or “/a/b/../c都是非法的。

zookeeper是保留字

ZNodes

  ZooKeeper tree中的每一个Node都指向一个znode, znode维护一个状态结构,结构中包含数据/acl 更新的版本号时间戳,二者共同用于验证缓存和同步更新。znode每更新一次 ,版本号增加,读取数据时会得到相应的版本号,更新数据时也应提供版本号,如果版本号不符,操作失败(注:提供强制模式,会忽略版本号)。

  Znode是应用访问最多的实体,有以下两个特性值得关注。

Watch

  Client可在znode上设置watch,znode更新触发并移除watch,通知信息将发送给设置了watch的Client.

数据存取Data Access

  namespace中znode存储的数据的读写是原子的,读写都作用到数据的全体,每个Node都有ACL控制访问权限。

  ZooKeeper并不是为通用数据库或对象存储设计的,相对地,它管理同步数据。数据可以是配置,状态信息,集结地等,它们的共同点是体积小(KB级)。Server和Client会确认数据大小不超过1M,实际平均值比这更小。操作相对较大的数据会导致一些操作用时大大增加,因为需要在网络间传输大量的数据到存储设备上。大文件存储可以使用NFS或者HDFS,同时在ZooKeeper中保存上述存储位置即可。

瞬时节点Ephemeral Nodes

  这种Node的生存期等于创建该它的会话的存活期,会话结束节点即被删除,因此这种node不能有子node.

序列节点Sequence Nodes

  创建node时可以请ZooKeeper在path结尾添加递增的计数器。每个父node拥有唯一的计数器,格式为%010d,即总长为10,用0填充。

注:计数值为int, 4字节,溢出时会出现负数。

ZooKeeper中的时间。

  ZooKeeper用多种方式跟踪时间。

Zxid

  对ZooKeeper状态的任何更改都会收到一个zxid,使得ZooKeeper的更改是完全有序的,较小的zxid对应的更改一定在较大的zxid操作之前。

版本号Version numbers

  对znode的每次更改都会导致node的某一版本号增加,一共有三种版本号,对应不同实体:

version     数据
cversion    子node
aversion    acl

计时Ticks

  当使用ZooKeeper的多Srever系统时,Server用tick计量事件时间,比如一次状态上传,会话超时,peer间连接超时等。tick time只通过会话超时(2倍tick time)来非直接地对外表示。如果Client请求的会话超时比小于系统最小值,Server将告诉它使用的是最小超时时间。

时钟时间Real time

  ZooKeeper只在znode创建和更改时向状态结构中添加的时间戳中使用时钟时间。

状态结构Stat Structure

  znode的状态结构stat structure包含以下域:

czxid
创建该Node的zxid.

mzxid
znode最后更改的zxid.

ctime
创建时的毫秒值

mtime
最后更改的毫秒值

version
对znode数据更改的number.

cversion
对子node更改的number.

aversion
acl更改number.

ephemeralOwner
拥有者的会话ID,非瞬时node值为0

dataLength
znode数据的长度.

numChildren
子node数.

会话ZooKeeper Sessions

  client创建handle来建立与ZooKeeper服务的会话,会话刚建立时,handle状态CONNECTING,client库会连接组成服务众多Server中的一个,连接成功后状态转换为CONNECTED。正常操作中会保持上述状态中的一个,如果遇到不可恢复的错误,如会话超时,授权失败或者主动关闭handle,状态会转换至CLOSED

  创建会话时需要提供一个包含server对应的ip:port字符串的List,Client库会随机选择一下连接,如果连接失败或者被断开,client会使用另一个地址,直到(重)连接成功。

3.2.0中添加的特性:可选择添加chroot到地址末,用来更改初始root目录,例如”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”,client将自动位于/app/a下,任何更改(如创建node)也是在此目录下。

  Client handle连接到服务后,ZooKeeper创建会话并分配一个64位整数(Session ID)给Client,如果Client要连接到另一个Server,握手时会提供这个Number。安全起见,ZooKeeper为会话创建所有Server能认证的password,并在会话建立时一起发送给Client,重连时Client将SessionID和password一并提供。

  Cient建立会话时可设置超时时间,服务能提供的最小值为tickTime的2倍,最大值为20倍。

  会话重连如果超时,Client状态会转为expired,一般来说不需要重新创建一个会话,因为Client库设计了相应的自动重连机制,但超时后可以重新建立会话。

  超时是由服务集群管理的,超时后所有eppheminal node被删除并通知设置了watch的进程,而原client只会在重新建立TCP连接后收到session expired”的notification。

  创建会话时可选用default watcher参数,Client的任何状态变化都会通知client,如会话超时,建立和断开。

  闲置状态时,Client可发送Ping请求来保持连接。

  连接建立后,一般来说以下两种情况执行同步/异步操作时会导致连接丢失:

1. 在失效的会话上进行操作
2. Clinet在有尚未完成的异步操作时从某一Server断开

Added in 3.2.0 — SessionMovedException. Client通常不会看到,发生于从某个连接收到请求,但会话已经转换到另一个Server时,通常是网络延时导致的。

监听/ZooKeeper Watches

  所有的读操作getData(), getChildren(), and exists()都可以设置watch. Watch触发是一次性的,当指定的数据更改时,消息发发送给Watch设置者。有以下三点需要关注。

One-time trigger

  例如client1设置了getData(“/znode1”, true),另一个Client修改或删除了znode1,Client1将收到消息,但之后znode1的修改就不会通知Client1了,除非再次设置Watch.

Sent to the client

  意味着消息可能在操作者收到返回码(操作完成)时还没有被设置watch的Client收到。watch消息是异步发送给Client的,ZooKeeper提供顺序保障,Client不会在收到消息之前看到它设置了watch的对象的变化。由于网络延时的其它因素的影响,不同的Client在收到消息和返回码上有先后,但是对同一个Client是保证有序的。

watch对象

  可理解为有两种watch,数据子node. getData() 和 exists() 设置数据watch, getChildren()设置子node watch,因此也可以理解为返回数据类型决定watch类型,所以setData()会触发数据Watch(操作失败则不会)。成功的create()会同时触发父node的子node watch和被创建node的数据watch,其它的类推。

  watch是由与client连接的Server本地维护的,有助于watch设置维护和分发的轻量化。当连接到另一个Server时,任何的session事件都会触发watch。断线重连后,之前注册的的watch会重新注册,需要的话也可触发。总之一切都是透明的,但有一种情况会丢失watch:watch一个尚不存在的znode,断线期间该node创建又被删除。

Watch有哪些保证

  对于watch,ZooKeeper保证以下三点:

watch相对其它事件、watch和异步回复都是有序的,client库保证所有事情都是有序分发的。

Client在看到新数据前收到watch

watch事件的顺序和server看到的事件发生顺序一致。

关于Watch的须知

  由于watch的一次性,如果想持续watch一个对象,那么每次收到消息后重新设置watch。

  由于一次性和延迟,你可能不会收到所有的更改,准备好处理两次消息之间znode已多次更改的情况,至少头脑中要有这个概念。

  同一类watch只会触发一次,即使之前设置了多次。

  连接断开后,只有在连接重新建立时才能收到watch,For this reason session events are sent to all outstanding watch handlers. Use session events to go into a safe mode: you will not be receiving events while disconnected, so your process should act conservatively in that mode.

Contents
  1. 1. ZooKeeper数据模型
  2. 2. ZNodes
    1. 2.1. Watch
    2. 2.2. 数据存取Data Access
    3. 2.3. 瞬时节点Ephemeral Nodes
    4. 2.4. 序列节点Sequence Nodes
  3. 3. ZooKeeper中的时间。
    1. 3.1. Zxid
    2. 3.2. 版本号Version numbers
  4. 4. 计时Ticks
    1. 4.1. 时钟时间Real time
    2. 4.2. 状态结构Stat Structure
  5. 5. 会话ZooKeeper Sessions
  6. 6. 监听/ZooKeeper Watches
    1. 6.1. One-time trigger
    2. 6.2. Sent to the client
  7. 7. watch对象
    1. 7.1. Watch有哪些保证
    2. 7.2. 关于Watch的须知