Zookeeper开发者手册
Zookeeperapi官网:http://zookeeper.apache.org/doc/r<version:版本号>/index.html
Zookeeper是一种作用于分布式应用高性能的调度服务。Zookeeper提供了公共的服务,在一组简单的接口中,例如例如命名、配置管理、同步和集群服务等,
因此你不需要从底层开始写这些服务。你可以使用现成的这些接口来实现一致性,组管理,选举和现场协议[?]等。你可以根据自己需求来建立。
整个API分为六大类:Overview、Developer、BookKeeper、Admin&Ops、Contributor、Miscellaneous;
这篇文档用来指导开发人员利用Zookeeper协调服务的特点创建分布式应用。它包含了理论和实际操作的知识。
文档的前四部分讲述了更高层次的不同的Zookeeper中的概念。这些概念都是必要的对于理解Zookeeper是如何工作的。
这里不包含源码,并且设定读者都是熟悉分布式计算面临的问题。
第一组(前四部分)的包括:
1.Zookeeper数据模型
2.Zookeeper会话
3.Zookeeper监视器
4.一致性保证
接下来的四部分提供了实用的编程事例:
1.构建:Zookeeper操作指南
2.绑定
3.用简单的例子展示程序结构
4.陷阱:常见的错误和解决
本文档中的大部分信息可作为独立的参考资料来访问。在你开始创建第一个Zookeeper应用时,请先至少读一下Zookeeper数据模型和Zookeeper基本操作的章节。
简单程序事例有助于理解基本的Zookeeper客户端应用的结构。
Zookeeper数据类型
Zookeeper具有层次化的命名空间,像一个分布式的文件系统。唯一的区别是在命名空间中每一个节点可以存放与它相关联的数据以及子节点。这类似与文件系统也允许一个文件也是一个目录。
节点的路径总是被表达成规范的、绝对的、以/为分割符的形式,没有相对路径。任何一个符合以下约束的unicode字符都可以在路径中使用:
1.The null character (\u0000) cannot bepart of a path name. (This causes problems with the C binding.)
2.The following characters can't be usedbecause they don't display well, or render in confusing ways: \u0001 - \u0019and \u007F - \u009F.
3.The following characters are not allowed:\ud800 -uF8FFF, \uFFF0 - uFFFF.
4.The "." character can be usedas part of another name, but "." and ".." cannot alone beused to indicate a node along a path, because ZooKeeper doesn't use relativepaths. The following would be invalid: "/a/b/./c" or"/a/b/../c".
5.The token "zookeeper" isreserved.
ZNodes
在Zookeeper树中的每一个节点都被称为一个znode。Znodes维护一个Stat结构体,包括数据更改的版本号、权限更改等,当然也包括时间戳。
数据版本号和时间戳提供了Zookeeper验证缓存并协调缓存的功能。每次znode数据更新,版本号都会加一。例如,当客户端检索服务器端的数据时,都会返回数据的版本号。
当客户端执行更新或者删除操作时,它必须提供正在修改的znode数据的版本号。当客户端提供的数据版本号与服务器的不匹配,则将会更新失败。
Note:Indistributed application engineering, the word node can refer to a generic hostmachine, a server, a member of an ensemble,
aclient process, etc. In the ZooKeeper documentation, znodes refer to the datanodes. Servers refer to machines that make up the ZooKeeper service;
quorumpeers refer to the servers that make up an ensemble; client refers to any hostor process which uses a ZooKeeper service.
znode是开发者要注意的主要抽象概念。在znode在这里有几个值得讲解的特性。监视器
客户端可以在Znode节点上设置监视器,该znode的变化将触发并清除监视器。当监视器触发时,Zookeeper会发送通知给客户端。更多信息在Zookeeper Watches章节中。
数据访问
在命名空间中存储在每一个znode节点中数据都是原子读写的。读取会一次性获取znode节点中的所有数据,写入会替换所有的数据。每一个节点有一个访问控制列表,用来限定谁能做什么操作。
Zookeeper不是为通用数据库或者存储大型对象设计的,相反是用来管理协调相关数据的。这些数据可以是配置信息、状态信息、汇聚信息等。这些协调数据的共同特点是它们都非常的小:大小在千字节测量。
Zookeeper的客户端和服务器端都会检查znode节点数据大小,确保znode数据小于1M,但是znode的数据平均大小应该远小于1M.因为需要更多的时间来通过网络传递数据或写入介质,所以操作相对比较大的数据会花费更多的时间和影响操作的响应时间。
如果一定要存储大数据,通常的处理方式是将数据存储在大容量存储系统中,例如NFS(网络文件系统协议)或者HDFS(分布式文件系统),然后将存储的指针存储在Zookeeper中。
临时节点
在Zookeeper中也有临时节点的概念。只要当创建这个znode的会话是活跃的,这些节点就会存在。当会话结束时,这个znode节点也会删除。由于临时节点的这种特性,所以它不允许存在子节点。
序列化节点-唯一命名
当创建znode节点是,你可以请求Zookeeper在路劲末尾增加单调递增计数器,这个数字对于父节点是唯一的,采用%010格式,即补零方式的10位数字(用于简化计数器排序顺序),例如"<path>0000000001",请参"QueueRecipe"中使用这种特性的例子.
注:这个用于生成下一个节点的数字是由父节点维护的一个整数(4字节),如果该数字超过2147483647,将溢出(结果导致产生一个名字"<path>-2147483647")。
Zookeeper中的时间
Zookeeper中有多种与时间相关的参数:
zxid
Zookeeper状态的改变都会有一个zxid标签(Zookeeper事务ID),这暴露Zookeeper中所有改变的总顺序。每一个对于zookeeper改变的Zookeeper标签都是唯一的,如果zxid1小于zxid2,则zxid1在zxid2之前发生。
Version numbers
对于节点的每一次改变都会导致节点的版本向上递增。三种版本号分别是:version(Znode数据的版本号),cversion(子节点改变的版本号)和aversion(访问控制的版本号)。
Ticks(客户端与服务器间的心跳检测时间)
当使用多服务器Zookeeper时,服务器使用Ticks来定义事件的时间,例如状态上载、会话超时、对等点之间的连接超时等。Tick Time(心跳时间)通过最小会话超时时间间接的暴露(2倍的Tick Times),如果客户端请求的会话超时小于最小会话超时,服务器将告诉客户端会话超时实际上是最小会话超时时间。
Real time
ZooKeeper不使用真实时间或时钟时间,例外情况是znode创建和修改时放入stat结构中的时间戳。
Zookeeper Stat Structure
Zookeeper中Znode节点的Stat结构体由以下几部分组成:
czxid:创建这个znode的zxid。
mzxid:最近一次修改这个znode的zxid。
pzxid:最近一次修改这个znode子节点的zxid。
ctime:这个znode的创建时间。
mtime:最近一次修改这个znode的时间。
dataVersion:这个znode数据的版本号.
cversion:这个znode子节点的修改版本号。
aversion:这个znode ACL的修改版本号。
ephemeralOwner:如果znode节点是临时节点 ,则这个节点是所有着的会话id;如果不是,则它的值是0。
dataLength:这个znode数据的长度。
numChildren:子节点的个数。
Zookeeper会话
与一种语言绑定,ZooKeeper客户端可以通过创建一个句柄,建立一个与ZooKeeper服务的会话。一旦创建,句柄就会在连接状态下(CONNECTING State),客户端库会尝试连接能构成Zookeeper服务的服务器之一,直到连接成功。在正常运行时就是这两种状态之一。如果发生不可恢复的错误,例如会话过期或者验证失败,或者应用程序显示关闭句柄,则句柄状态会变成CLOSED状态。下面这张图显示了Zookeeper可能发生的状态转换:、
要创建一个客户端会话,应用程序代码必须提供包含逗号分隔符的host:port列表的连接字符串,每一个端口对应于一个zookeeper服务器(例如:e.g."127.0.0.1:4545" or"127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002")。Zookeeper客户端库会挑选任意一台服务器然后尝试去连接它。如果连接失败,或者如果客户端由于某种原因连接失败,客户端将自动尝试连接下一台服务器,直到连接被重新建立。
下面是版本3.2.0一些新增功能:......
Zookeeper Watches
在Zookeeper中所以的读取操作:getData()、getChildren()和exists() - 都有一个选项:设置一个监视器,作为附带的功能。这里Zookeeper watch的定义是:监视事件是一次性触发的,它被发送到设置它的客户端,它设置的条件是它监视的数据发生更改时。这里有三个关键点在watch定义中需要考虑的:
一次性触发
当数据发生变化时,将向客户端发送一个监视事件。例如,如果客户端执行了getData(“/znode1”,true),后来对/znode1的数据发生的改变或者删除,客户端就会获得一个/znode1数据修改的watch事件。如果/znode1再次发生了修改,将不会发送watch事件,除非该客户再次执行读操作而设置一个新的监听器。
发送到客户端
这意味着一个事件正在发送给客户端的路上,在触发变化的客户端没有成功返回之前,事件不会到达客户端。监视器事件是异步发生给监视器的。Zookeeper提供了顺序操作的保证:客户端永远不会看到变化,直到它收到监听事件。网络延迟或者其他的因素可能导致不同的客户端从更新列表中看到监视事件和更新的返回值在不同的时间。关键是不同的客户端看到的一切都是有一致的顺序。(换个角度来解释:由于Watch有一次性触发的特点,所以在服务器端没有Watcher的情况下,Znode的任何变更就不会通知到客户端。不过,即使某个Znode设置了Watcher,且在Znode有变化的情况下通知到了客户端,但是在客户端接收到这个变化事件,但是还没有再次设置Watcher之前,如果其他客户端对该Znode做了修改,这种情况下,Znode第二次的变化客户端是无法收到通知的。这可能是由于网络延迟或者是其他因素导致,所以我们使用Zookeeper不能期望能够监控到节点每次的变化。Zookeeper只能保证最终的一致性,而无法保证强一致性。)
监视器设置的监视数据
节点改变有几种不同的方式。这有助于在zookeeper中维护两种监视器列表:数据监视器和子节点监视器。getData()和exists()设置数据监视器,getChildren()设置子节点监视器。或者它可以通过返回的数据类型来考虑监视器分类。getData() 和 exists()返回有关节点数据的信息,而getChildren()返回一系列子节点,因此,setData()将触发znode上数据的监视器(假设成功设置)。一个成功的create()操作将触发创建节点的数据监视器和父节点的子节点监控器。一个成功的delete()操作将会触发删除节点的监控器和子节点监视器,并且触发父节点子节点的监视器。
监视器维护在客户端连接的zookeeper服务器端,这样使监视器可以被轻量级地设置、维护和分发。当一个客户端连接到新服务器,对任何会话事件的监视器被触发。在与服务器断开连接时将不会接受到任何的监听器。当客户端再次连接,如果需要的话,以前注册的监视器将被再次注册和触发。有一种情况可能会被遗漏,就是在断开时创建或者删除znode。
监听器相关的术语
我们可以设置监视器通过三种的调用方式(读取zookeeper的状态):exists, getData, and getChildren。下面的列表详细说明了监听器可以触发的事件和启用他们的调用方式:
Created event:
Enabled with a call to exists.
Deleted event:
Enabled with a call to exists, getData, andgetChildren.
Changed event:
Enabled with a call to exists and getData.
Child event:
Enabled with a call to getChildren.
Zookeeper对于监视器的保证
对于监视器,zookeeper维护下面这些保证:
监视器关于其他事件,其他监视器异步回复都是按顺序的,zookeeper客户端库会确保一切都是按顺序发送的。
客户端会先看到znode的事件,然后再是znode的新数据。
Zookeeper中的监视事件顺序就是zookeeper服务所看到的更新顺序
监视器应该注意的事:
监视器是一次性触发器,你得到一个监视器事件后,如果你还想得到以后数据变化的通知事件,你必须再设置一个监视器。
由于监视器是一个一次性触发器,在得到一个事件和发送一个新监视器之间有时延,这期间你不能可靠保证得到该节点的变化。要考虑这样的情况:在得到事件与再次设置监视器之间,znode已变化了多次(你可能不会在意,但需要意识到这种情况的存在)。
一个监视器对象(或者说是方法/上下文对),对特定的通知只触发一次,例如,如果一个同样的监视器对象被注册成对同一个文件进行“exist”和”getData”监视,当这个文件被删除时,这个监视器对象只触发一次,即删除事件的通知。
当你与服务器断开(例如,服务器宕机了),在重新建立连接之前,你不会得到任何监视器消息,出于这种原因,会话事件被发送给所有未完成的监视器。使用会话事件进入安全模式:在断开期间你不会收到事件,所以你的程序此时应保守一些。
Zookeeper通过ACLs进行连接控制
Zookeeper用ACLs来控制对其节点的访问。ACL的实现与UNIX文件访问权限是非常相似的:它使用权限位来允许/拒绝对节点的各种操作以及能进行操作的范围。与标准Unix权限不同的是,一个Zookeeper节点不受三个标准的作用域限制:拥有者、组和其他人。Zookeeper的znode上没有所有者的概念,相反ACL会指定id集合与关联的权限。
注意,一个ACL仅仅适用于一个特定的znode,不适用与它的子节点。例如,如果/app只对ip:172.16.16.1可读,而/app/status对任何人可读,ACL不是递归的。
ZooKeor支持可插入的认证方案。
Id采用如下的形式:scheme:id,其中scheme是id所对应的认证方案。例如,对ip:172.16.16.1,id是主机的地址172.16.16.1。
当客户端连接到Zookeeper服务端并进行身份进行验证,Zookeeper将所有与客户端对应的ID与客户端连接关联。当客户端尝试访问节点时,这些Id与该节点的ACL进行验证。ACL由(scheme:expression, perms)构成的,expression的格式指定为scheme。例如,对(ip:19.22.0.0/16,READ)赋予READ权限给所有的起始ip为19.22的客户端。
ACL权限
Zookeeper支持以下的权限管理:
CREATE: you can create a child node(创建节点)
READ: you can get data from a node and listits children(获取节点数据从该节点或者子节点).
WRITE: you can set data for a node(设置节点数据)
DELETE: you can delete a child node(删除节点)
ADMIN: you can set permissions(设置权限,管理员?)
CREATE和DELETE权限从WRITE权限中分离出来,从而达到更加细粒度的访问控制。CREATE和DELETE的事例如下:
你希望A用户能设置节点的数据,但不允许创建或删除子节点。
有CREATE权限,但无DELETE权限:客户端在父节点创建Zookeeper节点。你希望所有的客户端都能添加,但是只有创建该父节点的才有删除的权力。
此外,因为没有文件所有者的概念,所以才有管理员权限。在某种意义上,管理员权限就是实体的所有者。ZooKeeper不支持LOOKUP权限(目录上的执行权限位允许你查看,即使你不能列出目录)。所有人有隐藏的LOOLUP权限,这允许你查看一个节点的状态,但不能做其他事情。
[未完待续]
参考自:
http://www.xuebuyuan.com/2205363.html
https://blog.****.net/z69183787/article/details/53023578
http://zookeeper.apache.org/doc/r3.4.11/zookeeperProgrammers.html