https://zookeeper.apache.org/...html
ZooKeeper is a distributed, open-source coordination service for distributed applications. It exposes a simple set of primitives that distributed applications can build upon to implement higher level services for synchronization, configuration maintenance, and groups and naming. It is designed to be easy to program to, and uses a data model styled after the familiar directory tree structure of file systems.
Zookeeper是高性能,高可用,严格有序的分布式协调服务,提供了统一配置(configuration),命名(naming),同步(synchronization),以及分组服务(group service)。node
同时,Zookeeper自己支持复制集群,实例间是两两链接的,维护内存中的数据状态,并持久存储中的事务日志和快照。只要大多数服务器可用,ZooKeeper服务将可用。
在“读为主”的工做负载中,它特别快。ZooKeeper应用程序可在数千台计算机上运行,而且在读取比写入更为常见的状况下,其性能最佳,比率约为10:1。shell
ZooKeeper提供的名称空间与标准文件系统的名称空间很是类似。apache
名称是由斜杠(/)分隔的一系列路径元素。ZooKeeper命名空间中的每一个节点都由路径进行惟一标识。编程
ZooKeeper的层次命名空间服务器
与标准文件系统不一样,ZooKeeper命名空间中的每一个节点均可以具备与其关联的数据以及子节点。就像拥有一个文件系统同样,该文件系统也容许文件成为目录。
每个节点均可以存储数据,只是须要注意的是存储的容量是有限,通常不能超过 1MiB。微信
Znode的类型分为三类:session
persistent node
)节点会被持久ephemeral node
),客户端断开链接后,ZooKeeper会自动删除临时节点sequential node
),每次建立顺序节点时,ZooKeeper都会在路径后面自动添加上10位的数字,从1开始,最大是2147483647 (2^32-1)每一个顺序节点都有一个单独的计数器,而且单调递增的,由Zookeeper的leader
实例维护。数据结构
Znode实际上有四种形式,默认是persistent
。app
create /test/a "hello"
,经过 create <path> <data>
参数指定为持久节点create -s <path> <data>
参数指定为顺序节点create -e <path> <data>
参数指定为顺序节点create -s -e <path> <data>
参数指定为临时及顺序节点(1) 建立顺序节点
[zk: 127.0.0.1:2281(CONNECTED) 0] create /seq_test/ "" Created /seq_test [zk: 127.0.0.1:2281(CONNECTED) 1] create -s /seq_test/s "hello" Created /seq_test/s0000000001 [zk: 127.0.0.1:2281(CONNECTED) 2] create -s /seq_test/s "hello" Created /seq_test/s0000000002 [zk: 127.0.0.1:2281(CONNECTED) 3] ls /seq_test [s0000000001, s0000000002]
(2) 建立临时节点
[zk: 127.0.0.1:2281(CONNECTED) 0] create /ephe_test/ "" Created /ephe_test [zk: 127.0.0.1:2281(CONNECTED) 1] create -e /ephe_test/e "hello" Created /ephe_test/e [zk: 127.0.0.1:2281(CONNECTED) 2] ls /ephe_test [e]
断开从新链接
[zk: 127.0.0.1:2281(CONNECTED) 0] ls /ephe_test []
(3) 建立临时顺序节点
[zk: 127.0.0.1:2281(CONNECTED) 0] create /ephe_seq_test/ "" Created /ephe_seq_test [zk: 127.0.0.1:2281(CONNECTED) 1] create -e -s /ephe_seq_test/s "hello" Created /ephe_seq_test/s0000000001 [zk: 127.0.0.1:2281(CONNECTED) 2] ls /ephe_seq_test [s0000000001]
ZooKeeper Transaction Id
)每次的变化都会产生一个集群全局的惟一的事务id, Zxid(ZooKeeper Transaction Id
),由Zookeeper的leader
实例维护。
这里的变化包括:
Server
Server
链接create
、修改set
、删除delete
,rmr
Zxid是一个64位的数字,高32位表示纪元,从1开始,每次选举出一个新的leader
,就会递增1;低32位是当前纪元维护的单调递增的数字,一样从1开始。
cZxid
:建立的事务标识。ctime
:建立的时间戳mZxid
:修改的事务标识,每次修改操做(set
)后都会更新mZxid
和mtime
。mtime
:修改的时间戳pZxid
:直接子节点最后更新的事务标识,子节点有变化(建立create
、修改set
、删除delete
,rmr
)时,都会更新pZxid
。cversion
:直接子节点的版本号。当子节点有变化(建立create
、修改set
、删除delete
,rmr
)时,cversion
的值就会增长1。dataVersion
:节点数据的版本号,每次对节点进行修改操做(set
)后,dataVersion
的值都会增长1(即便设置的是相同的数据)。aclVersion
:节点ACL的版本号,每次节点的ACL进行变化时,aclVersion
的值就会增长1。ephemeralOwner
:当前节点是临时节点(ephemeral node
)时,这个ephemeralOwner
的值是客户端持有的session
id。dataLength
:节点存储的数据长度,单位为 B (字节)。numChildren
:直接子节点的个数。➜ zkCli.sh -server 127.0.0.1:2281 [zk: 127.0.0.1:2281(CONNECTED) 0] get / cZxid = 0x0 ctime = Thu Jan 01 08:00:00 CST 1970 mZxid = 0x0 mtime = Thu Jan 01 08:00:00 CST 1970 pZxid = 0x0 cversion = -1 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 1
默认根节点 / 和 /zookeeper 是存在,所以 cZxid 是 0x0。
[zk: 127.0.0.1:2281(CONNECTED) 1] ls / [zookeeper] [zk: 127.0.0.1:2281(CONNECTED) 2] create /test "hello" Created /test [zk: 127.0.0.1:2281(CONNECTED) 3] ls / [zookeeper, test]
当建立了一个 /test 节点后,根节点的子节点就多出来了。
[zk: 127.0.0.1:2281(CONNECTED) 4] get /test hello cZxid = 0x100000002 ctime = Sat May 23 15:43:10 CST 2020 mZxid = 0x100000002 mtime = Sat May 23 15:43:10 CST 2020 pZxid = 0x100000002 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 5 numChildren = 0
为何cZxid
高32位是 0x1 代表了当前纪元为第一代,低32位是00000002 代表了当前纪元第2笔事务操做建立了 /test 节点。
为何是2呢?由于咱们是经过 zkCli.sh 客户端链接到Server
的,这里会消耗一次 Zxid。
[zk: 127.0.0.1:2281(CONNECTED) 5] set /test "hello world" cZxid = 0x100000002 ctime = Sat May 23 15:43:10 CST 2020 mZxid = 0x100000003 mtime = Sat May 23 15:43:41 CST 2020 pZxid = 0x100000002 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 11 numChildren = 0
修改 /test 节点数据,mZxid
,mtime
和 dataVersion
发生了变化, dataLength
变为了( "hello world"占用了11个字节)。
[zk: 127.0.0.1:2281(CONNECTED) 6] create /test/a "" Created /test/a [zk: 127.0.0.1:2281(CONNECTED) 7] get /test hello world cZxid = 0x100000002 ctime = Sat May 23 15:43:10 CST 2020 mZxid = 0x100000003 mtime = Sat May 23 15:43:41 CST 2020 pZxid = 0x100000004 cversion = 1 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 11 numChildren = 1
建立 子节点 /test/a,咱们查看 /test 节点属性,发现 pZxid
,cversion
, numChildren
都发生了变化。
[zk: 127.0.0.1:2281(CONNECTED) 8] get /test/a cZxid = 0x100000004 ctime = Sat May 23 15:44:12 CST 2020 mZxid = 0x100000004 mtime = Sat May 23 15:44:12 CST 2020 pZxid = 0x100000004 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 0
查看 /test/a 节点属性,发现 cZxid
与 父节点的 pZxid
是一致的,证明了 pZxid
是直接子节点最后更新的事务标识。
ZooKeeper支持 Watch。客户端能够在znode上设置 Watch。
znode更改时,将触发并删除监视。触发监视后,客户端会收到一个数据包,说明znode已更改。
若是客户端与其中一个ZooKeeper服务器之间的链接断开,则客户端将收到本地通知。
3.6.0中的新增功能:
客户端还能够在znode上设置永久性的递归监视,这些监视在触发时不会删除,而且会以递归方式触发注册znode以及全部子znode的更改。
支持 Watch的 客户端命令:
stat path [watch]
ls path [watch]
ls2 path [watch]
get path [watch]
[zk: 127.0.0.1:2281(CONNECTED) 3] get /test/d watch cZxid = 0x100000013 ctime = Sat May 23 16:47:41 CST 2020 mZxid = 0x100000013 mtime = Sat May 23 16:47:41 CST 2020 pZxid = 0x100000013 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 0
此时使用另一个客户端去更改 /test/d 节点的数据,咱们就能够看到原来的客户端自动收到了一个WATCHER 通知。
[zk: 127.0.0.1:2281(CONNECTED) 4] WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/test/d
@SvenAugustus( https://www.flysium.xyz/)
更多请关注微信公众号【编程不离宗】,专一于分享服务器开发与编程相关的技术干货:
![]()