zookeeper原理

zookeeper数据模型
zookeeper拥有一个层次的命名空间,命名空间中的每个节点可以和它自身或它的子节点相关联的数据,这就好像一个文件系统,只不过文件系统中的文件还可以具有目录功能。

Znode
zookeeper目录树中每一个节点对应着一个Znode。每个Znode维护着一个属性结构,包含数据的版本号(dataVersion)、时间戳(ctime、mtime)等状态信息。

Znode是客户端访问的zookeeper的主要实体,包含以下几个主要特征:

(1)watchs

客户端可以在节点上设置watch(可以称之为监视器)。当节点状态发生改变时将会触发watch对应的操作。当watch被触发时,zookeeper将会向客户端发送且仅发送一个通知,因为watch只能被触发一次。

(2)数据访问

zookeeper中每个节点上存储的数据需要被原子性的操作,也就是说读操作将获取与节点相关的所有数据,写操作也将替换掉节点的所有数据。

(3)临时节点

zookeeper中节点有两种,分别为临时节点和永久节点。节点的类型在创建时即被确定,并且不能改变。zookeeper临时节点的生命周期依赖于创建它们的会话,一旦会话结束,临时节点将会被自动删除,也可以手动删除,临时节点不允许拥有子节点。永久节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,它们才会被删除。

(4)顺序节点(唯一性保证)

当创建Znode的时候,用户可以请求在zookeeper的路径结尾添加一个递增的计数。这个计数对于此节点的父节点来说是唯一的,它的格式为

zookeeper中的时间
zookeeper中有多种记录时间的方式
(1)Zxid
对每个节点的每一个操作都将使节点接收到一个zxid格式的时间戳,并且这个时间戳是全局有效的,也就是说每一个对节点的改变都将产生一个唯一的zxid。zookeeper的每个节点都维护着3个zxid值,分别为:cZxid(创建时间戳)、mZxid(修改时间戳)、pZxid

1
2
3
4
5
6
7
8
9
10
11
12
13
[zk: localhost:2181(CONNECTED) 3] ls2 /pucong
[a1]
cZxid = 0x100000014
ctime = Wed Oct 15 12:19:38 CST 2014
mZxid = 0x100000017
mtime = Wed Oct 15 12:34:58 CST 2014
pZxid = 0x100000031
cversion = 11
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 1

(2)版本号
对每个节点的每一个操作都将使得这个节点的版本号增加,每个节点维护着3个版本号,它们分别为dataVersion(节点数据版本号)、cversion(子节点版本号)、aclVersion(节点拥有的ACL的版本号)

1
2
3
4
5
6
7
8
9
10
11
12
13
[zk: localhost:2181(CONNECTED) 2] ls2 /pucong
[a1]
cZxid = 0x100000014
ctime = Wed Oct 15 12:19:38 CST 2014
mZxid = 0x100000017
mtime = Wed Oct 15 12:34:58 CST 2014
pZxid = 0x100000031
cversion = 11
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 1

zookeeper watchs
zookeeper可以为所有的读操作设置watch,这些读操作包括:exists()、getChildren()、getData()。watch事件是一次性的触发器,当watch的对象状态发生改变时,将会触发此对象上所设置的watch对应的事件。

zookeeper所管理的watch可以分为2类,一类是数据watch(data watchs),一类是子watch(child watchs)。

getData()和exists()负责设置数据watch,getChildren()负责孩子watch。因此,setData()将触发设置了数据watch的对应事件,一个成功的create()操作将触发Znode的数据watch以及孩子watch。一个成功的delete()操作将触发数据watch和孩子watch,因为Znode被删除的时候,它的child watch也将被删除。