学习zookeeper—基础
Posted SanW
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习zookeeper—基础相关的知识,希望对你有一定的参考价值。
目录
1 zookeeper 数据模型基本操作
2 zoo.cfg 配置
3 zookeeper 基本数据模型
4 zookeeper 作用的体现
5 zookeeper 常用命令
6 Acl权限控制
7 zk四字命令
8 集群
1 zookeeper数据模型基本操作
进入zookeeper的bin目录下
zookeeper服务端:
启动zookeeper服务端 :./zkServer.sh start
重启zookeeper服务端:./zkServer.sh restart
查看zookeeper服务端状态:./zkServer.sh status
关闭zookeeper服务端:./zkServer.sh stop
zookeeper客户端:
启动zookeeper客户端:./zkCli.sh
退出zookeeper客户端:Ctrl + C
2 zoo.cfg配置
进入zookeeper的conf目录下,复制一份zoo_sample.cfg,命名为zoo.cfg并保存在该目录下。
打开zoo.cfg文件:
如图所示:
1、
initLimit 和 syncLimit 的值分别为 10和5,指的是他们的值分别为 10倍的tickTime 和 5倍的tickTime。
2、
dataDir用于存储Snapshot数据
3 zookeeper基本数据模型
1、
临时节点可以人为的创建、删除,当session失效后,临时节点的数据全都会丢失。
4 Zookeeper作用的体现
1、
当A获取到锁,其他服务器进入阻塞等待,直到A释放锁,B再获取锁.......
当主节点(第一个)写入了数据(Data-XYZ),它会自动的将这些数据同步到从节点,客户端可以在主节点或者从节点中读取数据,这就是数据一致性的表现。
5 Zookeeper常用命令
1、
1)启动zk服务端和客户端;
2)ls path:进入path节点
3)ls -s path:进入path节点,并且输出状态信息,ls -s path 命令就相当于 ls path 命令加 stat path 命令
4)stat path:path节点下的状态信息
cZxid:当前节点创建后zookeeper分配给该节点的id;
ctime:当前节点创建的时间;
mZxid:当前节点修改后zookeeper分配给该节点的id;
mtime:当前节点的修改时间,当mtime等于ctime时,就说明该节点未被修改过;
pZxid:当前的子节点的id;
cversion:当前的子节点的更改次数;
dataVersion:当前节点的数据版本号,每当修改当前节点的数据时,dataVersion都会加1,也就是说dataVersion就是修改当前节点的次数;
aclVersion:当前节点的ACL进行更改的次数;
ephemeralOwner:如果当前节点是ephemeral类型节点,则这是znode所有者的 session ID。 如果znode不是ephemeral节点,则该字段设置为零;
dataLength:当前节点数据字段的长度。
numChildren:当前节点的子节点的数量。
5)get path:把path节点下的数据取出来
这里为空,还没有创建设置节点
5.1 zk特性——session
客户端向服务端的ping包请求是为了告诉服务端,客户端还活着,刷新session超时时间。
2、创建节点
创建节点的方式:
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
-s: 顺序节点
-e: 临时节点
-c: 容器节点
-t: 可以给节点添加过期时间,默认禁用,需要通过系统参数启用
1)创建一个持久节点 create /programmer programmer-data
2)查看创建的节点的值 get /programmer
查看检点的值和状态信息 get -s /programmer
3)查看创建的节点的状态信息 stat /programmer
3)创建一个临时子节点 create -e /programmer/tem tem-data
4)查看临时节点的状态信息 stat /programmer/tem
如果节点的ephemeralOwner值类似于上图中ephemeralOwner的值,则说明该节点就是临时节点。
如果在超时时间内未收到临时节点的心跳信号,则会把该临时节点删除掉(不管是否已经把客户端连接给断开)。
5)创建顺序节点 create -s /programmer/items
也可以在创建顺序节点时,在后面加上数字,表示是第几个节点:create -s /programmer/items 1
6)创建顺序临时节点 create -s -e /programmer/items
7)创建容器节点 create -c /programmer/items
容器节点用来容纳子节点,若没有子节点,容器节点表现跟持久化节点一样,如果给容器节点创建子节点,后续又把子节点删除,那么容器节点也会被zookeeper删除,当然不是立即删除,而是在一个时间段内被删除
8)节点监听 get -w /programmer/items
针对节点的监听(一次性),一旦时间触发,对应的注册立即被删除
9)修改节点的值 set /programmer new-data
** set使用的是乐观锁:假设并发修改值时,可以使用 set /programmer data 1(版本号)命令。
**意思就是说:我修改值之前的版本号为1,修改成功后版本号变为2,如果并发修改值时,版本号就起作用了,有两人使用 set /programmer data 1 时,其中一个人先修改成功,版本号变为2,由于版本号变为2了,另外一个人修改数据写的版本号却是1,会报错修改失败。
10)删除节点 delete /programmer/tem
**delete也是使用乐观锁:假设并发删除时,可以使用 delete /programmer/tem 1(版本号)命令。
**意思就是说:与修改同理,删除之前的版本号如果不是1,则删除失败。
5.2 zk特性——watcher
1、
2、命令使用:
注意:新版本的watch不是使用 get path[watch] 来设置watcher监听(使用这个命令也也可以),是使用 get [-w] path来设置watcher。
如图,带有 [-w] 的都可以创建watcher监听:
事件类型一:
1)创建父节点时触发:
输入:
(1)创建监听
stat -w /stady
这里会显示节点不存在,但是不影响他创建watcher监听。
(2)创建该节点,触发创建节点事件
create /stady data
(3)如图所示,创建该节点后触发了 type 为 NodeCreated 事件,修改该目录的值后却不会再触发事件,因为watcher是一次性的,触发过一次后立即销毁。
2)修改父节点时触发:
输入:
(1)创建监听(创建监听方式有多种,如上面所述,带有 [-w] 的命令都可以创建)
get -w /stady
(2)修改该节点,触发修改节点事件
set /stady data
(3)如图所示,修改该节点后触发了 type 为 NodeDataChanged 事件
3)删除事件这里就不再演示,方法一样。
事件类型二:
1)创建子节点时触发
输入:
(1)创建子节点事件
ls -w /stady
(2)创建子节点
create /stady/item
2)删除子节点时触发
输入:
(1)创建子节点事件
ls -w /stady
(2)删除子节点
delete /stady/item
3)创建和删除子节点触发的事件都是 NodeChildrenChanged ,修改子节点不会触发事件。
4)把子节点当作父节点来设置watcher监听(创建节点时触发)
输入:
(1)创建节点事件
stat -w /stady/item
(2)创建节点
create /stady/item
如图所示,以这种方式创建子节点的watcher事件,可以触发增、删、改事件,并且输出的type不是都为 NodeChildrenChanged。
5)删除、修改方法一致,这里不再演示。
6 ACL 权限控制
1、
命令行操作:
1)查看权限
getAcl /stady/item
2)设置权限,只有删除和写入权限
setAcl /stady/item world:anyone:dw
3)如图所示,设置权限需要根据查看权限输出的 \'world,\'anyone 来设置的,并且可以看出他有cdrwa权限(创建、删除、读、写、设置权限);
给他设置了dw权限(删除,写)后,输入了读命令,输出了没有权限读取。
4)命令行使用,如图:
Auth模式
1)注册用户命令
addauth digest root:root
2)赋予权限
setAcl /stady/test auth:root:root:cdrwa
或
setAcl /stady/test auth::cdra
3)查看权限
如图所示:root的密码是被加密过的,加密的方式是先使用SHA1后使用base64。
4)如果退出了客户端,用户也会退出登录,重启客户端后,如果要设置权限可以使用:
setAcl /stady/test digest:root:qiTlqPLK7XM2ht3HMn02qRpkKIE=
注意:这样子设置权限的话,需要输入密文的密码。除此之外,还不能get设置了相应权限的节点。
5)当我们退出用户后,我们可以重新登录,登录密令与注册密令一样:
addauth digest root:root
重新登录后,再设置权限就不需要像 8) 那样麻烦了。
ip模式
IP 模式表示有相同 IP 地址的任何用户,通过 IP 地址粒度来进行权限控制,例如配置了ip:192.168.0.110
,即表示权限控制都是针对这个IP地址的。同时,IP 模式也支持按照网段的方式进行配置,例如ip:192.168.0.1/24
表示针对192.168.0.*
这个IP段进行权限控制。
1)创建节点:
2)设置ip权限
setAcl /stady/ip ip:192.168.179.129:cdwra
super模式
1、修改zkServer.sh,增加super管理员;
2、重启zkServer.sh。
1)复制zkServer.sh(各位小伙伴可以不复制,直接修改zkServer.sh,为了保险起见,建议复制一份出来修改)
cp zkServer.sh ./zkServer2.sh
2)进入zkServer2.sh
vim zkServer2.sh
3)输入命令,快速定位到nohup
/nohup
4)修改zkServer2.sh
5)启动zkServer2.sh 启动zkCli.sh 后,如图演示:
如上图,使用了 get /stady/winip 命令,返回无权限,登录超级管理员用户后,再使用 get /stady/winip 命令,返回除了结果。
Digest模式和World模式,这里不在演示。
小结:
7 zk四字命令
1)退出zookeeper服务端和客户端,安装Ncat
yum install nc
stat 命令
stat 命令用于查看 zk 的状态信息
2)启动zookeeper服务端后,输入
echo stat | nc localhost 2181
3)如果报错:stat is not executed because it is not in the whitelist.
前往 zoo.cfg 文件里面添加:
#开启四字命令
4lw.commands.whitelist=*
4)重启服务端后,输入 2)命令
ruok 命令
ruok 命令用于查看当前 zkserver 是否启动,若返回 imok 表示正常。
5)输入
echo ruok | nc localhost 2181
结果
dump 命令
dump 命令用于列出未经处理的会话和临时节点。
6)输入
echo dump | nc localhost 2181
结果
conf 命令
conf 命令用于查看服务器配置。
7)输入
echo conf | nc localhost 2181
结果
cons 命令
cons 命令用于展示连接到服务器的客户端信息。
8)输入
echo cons | nc localhost 2181
结果
envi 命令
envi 命令用于查看环境变量。
9)输入
echo envi | nc localhost 2181
mntr 命令
mntr命令用于查看健康信息
10)输入
echo mntr | nc localhost 2181
wchs 命令
wchs 命令用于查看触发器信息
echo wchs | nc localhost 2181
还有 wchc 与 wchp 命令,用于session与watch及path与watch信息。
8 zookeeper 集群
8.1 在同一台虚拟机搭建zookeeper集群
1)基本概念
一个主节点 xx ,两个从节点 yy 和 zz ,当主节点 xx 宕机或者崩了,就出现选举一个从节点当作一个主节点,当 xx 修复好后,会回来充当从节点。
2)搭建
1、进入zookeeper的配置文件夹(conf)
2、编辑配置文件
vim zoo.cfg
(为了方便,本人把apache-zookeeper-3.6.3-bin文件名改为了zookeeper01,把Dir路径也修改了一下,大家根据自己需求命名存放路径,如下图所示)
注意:要把环境变量也更改了,如果不更改,则每次启动zookeeper都要进入zookeeper的bin目录下使用 ./zkServer.sh start 等命令才能起作用。添加了环境变量,在哪个目录下直接使用 ./zkServer.sh start 等命令都能起作用。
添加:
server.1-3为 主/从 zookeeper 的名称,ip地址(192.168.5.188)为虚拟机的ip地址,后面的端口号自定义。
3、进入dataDir 路径
这里的dataDir路径为 /usr/local/zookeeper/zookeeper01/conf/tmp/data
进入后直接使用下面命令,来创建 myid
vim myid
输入以上命令,会自动创建myid文件,并且进入该文件,在该文件里面添加一个 “1” 即可。
4、进入第四步,解压两份zookeeper文件到同级目录,分别命名为zookeeper02、zookeeper03
5、进入zookeeper02的zoo.cfg文件,修改端口号
然后进入zookeeper02的dataDir路径,创建myid文件
vim myid
进去后把 “1” 改为 “2”
6、重复 5 步骤,修改zookeeper03的zoo.cfg文件的端口号为2183,并且修改myid文件,把 “1”改为 “3”
7、配置完成后,启动这三个(zookeeper01 - zookeeper03)的服务端
//进入这三个zookeeper文件的bin目录分别输入: ./zkServer.sh start
8、启动server.1的客户端,并且添加节点
#启动server.1的客户端 ./zkCli.sh -server localhost:2181 #添加节点 create /cluster data
9、关闭server.1的客户端,启动server.2的客户端
#使用 Ctrl + C 关闭server.1的客户端 #启动server.2的客户端 ./zkCli.sh -server localhost:2182
启动成功后 输入:
ls /
就会发现在server.1中又创建的所有节点
10、同理,关闭server.2的客户端,打开server.3的客户端,也是能查看到server.1中的节点。
11、在server.1、server.2或在server.3创建节点,都能将创建的节点同步到其他的server中。
8.2 在不同虚拟机上搭建zookeeper集群
注意:配置文件中,ip地址不同,端口号可以相同
1、首先准备三台虚拟机
我这里使用了克隆两台虚拟机:
第一台:192.168.5.128
第二台:192.168.5.129
第三台:192.168.5.130
2、更改 zoo.cfg 文件:
说明:我这里的三台zookeeper的路径、命名都是一样的,使用的端口号也都是一致的。
第一台虚拟机:
myid文件为1
第二台:
myid文件为2
第三台:
myid文件为3
3、启动服务端
打开这三台虚拟机,分别启动他们的服务端。
4、启动客户端
第一台虚拟机:
./zkCli.sh -server 192.168.5.128:2181 #创建节点 create /test T
可以不退出第一台的客户端。
第二台虚拟机:
./zkCli.sh -server 192.168.5.129:2181 #查看节点 ls / #查看第一台创建的test节点 get /test
第三台虚拟机同样这么操作,都是可以显示出所有节点。
5、查看是否为主节点或是从节点
./zkServer.sh status
如下图所示,则为从节点
6、测试宕机
1)直接关闭第一台虚拟机;
2)剩下两台虚拟机中的zookeeper会经过选举机制,最终选举其中一个zookeeper为主节点;
3)分别向这两台虚拟机输入:
./zkServer.sh status
4)其中一台就会打印出:
说明这台虚拟机中的zookeeper当选上了主节点
5)从新开启第一台虚拟机,并启动zookeeper服务端,输入
./zkServer.sh status
结果:
这表明当主节点宕机后,从节点会选举出一个来当主节点。当主节点被修复后,会被列入从节点。
[转帖]Zookeeper学习系列 教会你Zookeeper的一些基础概念
Zookeeper学习系列【一】 教会你Zookeeper的一些基础概念
前言
最近加入了部门的技术兴趣小组,被分配了Zookeeper的研究任务。在研究过程当中,发现Zookeeper由于其开源的特性和其卓越的性能特点,在业界使用广泛,有很多的应用场景,而这些不同的应用场景实际上底层的原理都是差不多的,只要你真正理解了Zookeeper的一些基础概念和机制,就能够触类旁通。
于是乎,在第一次和项目小组内成员分享过Zookeeper作为服务注册中心的原理和客户端demo演示之后,我萌生出了整理一个专题的想法,以此为起点,慢慢捡起自己的博客分享之路。
本篇的内容主要介绍以下几点:
- What is Zookeeper
- Zookeeper 数据模型
- Zookeeper 服务基本操作
- Sessions
- Watches
- 总结
一、What is Zookeeper
我最早接触Zookeeper是因为我们项目使用的微服务治理架构是Dubbo,Dubbo推荐使用的服务注册中心就是Zookeeper。从本质上来说,Zookeeper就是一种分布式协调服务,在分布式环境中协调和管理服务是一个复杂的过程。ZooKeeper通过其简单的架构和API解决了这个问题。 ZooKeeper允许开发人员专注于核心应用程序逻辑,而不必担心应用程序的分布式特性。Zookeeper最早的应用是在Hadoop生态中,Apache HBase使用ZooKeeper跟踪分布式数据的状态。
实际上从它的名字上就很好理解,Zoo - 动物园,Keeper - 管理员,动物园中有很多种动物,这里的动物就可以比作分布式环境下多种多样的服务,而Zookeeper做的就是管理这些服务。
ZooKeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。
原语: 操作系统或计算机网络用语范畴。是由若干条指令组成的,用于完成一定功能的一个过程。具有不可分割性·即原语的执行必须是连续的,在执行过程中不允许被中断。
Zookeeper提供服务主要就是通过:数据结构 + 原语集 + watch机制达到的。
分布式应用程序结合Zookeeper可以实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。
二、Zookeeper 数据模型
ZNode
从上图可以看到,Zookeeper的数据模型和Unix的文件系统目录树很类似,拥有一个层次的命名空间。这里面的每一个节点都被称为 - ZNode, 节点可以拥有子节点,同时也允许少量数据节点存储在该节点之下。(可以理解成一个允许一个文件也可以是一个目录的文件系统)
(1)节点引用方式
ZNode通过路径引用,如同Unix中的文件路径。路径必须是绝对的,因此他们必须有斜杠字符/
来开头,除此之外,路径名必须是唯一的,且不能更改。
这个特性在Dubbo的服务注册上也有体现,Dubbo源码中有个贯穿全局的类URL
,dubbo是以总线模式来时刻传递和保存配置信息的,也就是配置信息都被放在URL
上进行传递,随时可以取得相关配置信息。Dubbo在向注册中心注册时写下的节点名就是由URL
中的URI
和配置信息编码后组成的。如下图。
这属于这部分知识的扩展内容,在之后服务注册中心的章节会更具体的说明。
(2)ZNode结构
前面提到过,ZNode兼具文件和目录两种特点,既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分。
ZNode由以下几部分组成:
-
Stat数据结构
-
操作控制列表(ACL) - 每个节点都有一个ACL来做节点的操作控制,这个列表规定了用户的权限,限定了特定用户对目标节点的操作
- CREATE - 创建子节点的权限
- READ - 获取节点数据和子节点列表的权限
- WRITE - 更新节点数据的权限
- DELETE - 删除子节点的权限
- ADMIN - 设置节点ACL的权限
-
版本 - ZNode有三个数据版本
- version - 当前ZNode的版本
- cversion - 当前ZNode子节点的版本
- aversion - 当前ACL列表的版本
-
Zxid
- 可以理解成Zookeeper中时间戳的一种表现形式,也可以理解成事务ID的概念
- 如果Zxid1的值小于Zxid2的值,那么Zxid1所对应的事件发生在Zxid2所对应的事件之前。
-
ZooKeeper的每个节点维护者三个Zxid值,分别为:cZxid、mZxid、pZxid。
- cZxid:节点创建时间 create
- mZxid:节点最近一次修改时间 modify
- pZxid:该节点的子节点列表最后一次被修改时的时间,子节点内容变更不会变更pZxid
-
- data域
- children节点
下面有几个需要注意的知识点着重讲一下:
A. 状态信息/节点属性
下图是我在服务器上使用zkClient,用get命令获取到的某个Dubbo微服务接口节点的状态信息,来作为示例,
[zk: localhost:2181(CONNECTED) 0] get /dubbo/com.***.microservice.ucs.api.UniqueControlApi
127.0.0.1 // 节点数据Data域
cZxid = 0xdd59 //Created ZXID,表示该ZNode被创建时的事务ID
ctime = Thu Apr 18 15:17:11 CST 2019 //Created Time,表示该ZNode被创建的时间
mZxid = 0xdd59 //Modified ZXID,表示该ZNode最后一次被更新时的事务ID
mtime = Thu Apr 18 15:17:11 CST 2019 //Modified Time,表示该节点最后一次被更新的时间
pZxid = 0xdd62 //表示该节点的子节点列表最后一次被修改时的事务ID。注意,只有子节点列表变更了才会变更pZxid,子节点内容变更不会影响pZxid。
cversion = 4 //子节点的版本号
dataVersion = 0 //数据节点版本号
aclVersion = 0 //ACL版本号
ephemeralOwner = 0x0 //创建该节点的会话的sessionID。如果该节点是持久节点,那么这个属性值为0。
dataLength = 9 // Data域内容长度
numChildren = 4 // 子节点个数 众所周知,Dubbo接口子节点分为providers/configurators/routers/consumers
B. Data域
关于Data域,Zookeeper中每个节点存储的数据要被原子性的操作,也就是说读操作将获取与节点相关的所有数据,写操作也将替换掉节点的所有数据。
值得注意的是,Zookeeper虽然可以存储数据,但是从设计目的上,并不是为了做数据库或者大数据存储,相反,它是用来管理调度数据,比如分布式应用中的配置文件信息、状态信息、汇集位置等,这些数据通常是很小的数据,KB为大小单位。ZNode对数据大小也有限制,至多1M。实际上从这里,就可以推导出Zookeeper用于分布式配置中心的可行性。
C. Zxid
在ZooKeeper中,能改变ZooKeeper服务器状态的操作称为事务操作。一般包括数据节点创建与删除、数据内容更新和客户端会话创建与失效等操作。对应每一个事务请求,ZooKeeper都会为其分配一个全局唯一的事务ID,用Zxid表示。
由上图的示例可以看出,Zxid是一个64位的数字。前32位叫做epoch,用来标识Zookeeper 集群中的Leader
节点,当Leader
节点更换时,就会有一个新的epoch。后32位则为递增序列。从这些Zxid中可以间接地识别出ZooKeeper处理这些事务操作请求的全局顺序。
(3)节点类型
ZNode节点类型严格来说有四种:持久节点、临时节点、持久顺序节点、临时顺序节点
- PERSISTENT 持久节点 - 该节点的生命周期不依赖于session,创建之后客户端断开连接,节点依旧存在,只用客户端执行删除操作,节点才能被删除;
- EPHEMERAL 临时节点 - 该节点的声明周期依赖于session,客户端断开连接,临时节点就会自动删除。另外,临时节点不允许有子节点。
- SEQUENTIAL 顺序节点 - 当选择创建顺序节点时,ZooKeeper通过将10位的序列号附加到原始名称来设置znode的路径。例如,如果将具有路径
/myapp
的znode创建为顺序节点,则ZooKeeper会将路径更改为/myapp0000000001
,并将下一个序列号设置为0000000002
。如果两个顺序节点是同时创建的,那么ZooKeeper不会对每个znode使用相同的数字。顺序节点在锁定和同步中起重要作用。
三、Zookeeper服务基本操作
如上图,标明了Zookeeper服务的九种基本操作,进入ZkClient.sh
,使用help
,可以看到这几种操作。
[zk: localhost:2181(CONNECTED) 1] help
ZooKeeper -server host:port cmd args
stat path [watch] // 获取指定节点的状态信息
set path data [version] // setData操作
ls path [watch] // 查看某个节点下的所有子节点信息
delquota [-n|-b] path // 删除节点配额
ls2 path [watch] // ls + stat 两个命令结合
setAcl path acl // 设置ACL
setquota -n|-b val path // 设置节点配额,-n 是限制子节点个数 -b是限制节点数据长度
history // 历史命令
redo cmdno // 执行历史命令
printwatches on|off
delete path [version] // 删除指定路径节点,有子节点需要先删除子节点
sync path // 同步视图
listquota path // 查看节点配额信息
rmr path // 删除节点及其子节点
get path [watch] // 获取当前节点数据内容
create [-s] [-e] path data acl // 创建节点
addauth scheme auth
quit
getAcl path // 获取ACL
close
connect host:port
从命令中可以看到,更新ZooKeeper操作是有限制的。delete或setData必须明确要更新的Znode的版本号,我们可以调用exists找到。如果版本号不匹配,更新将会失败。
更新ZooKeeper操作是非阻塞式的。因此客户端如果失去了一个更新(由于另一个进程在同时更新这个Znode),他可以在不阻塞其他进程执行的情况下,选择重新尝试或进行其他操作。
四、Sessions
在 ZooKeeper 中,一个客户端连接是指客户端和服务器之间的一个 TCP 长连接。客户端启动的时候,首先会与服务器建立一个 TCP 连接,从第一次连接建立开始,客户端会话的生命周期也开始了。通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向Zookeeper服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的Watch事件通知。
客户端以特定的时间间隔发送心跳以保持会话有效。如果ZooKeeper Server Ensembles在超过服务器开启时指定的期间(会话超时)都没有从客户端接收到心跳,则它会判定客户端死机。
会话超时通常以毫秒为单位。当会话由于任何原因结束时,在该会话期间创建的临时节点也会被删除。
五、Watches
在我看来,Watches - 监听事件,是Zookeeper中一个很重要的特性,也是实现Zookeeper大多数功能的核心特性之一。简单来说, Zookeeper允许Client端在指定节点上注册Watches,在某些特定事件触发的时候,Zookeeper服务端会将事件异步通知到感兴趣(即注册了Watches)的客户端上去。可以理解成一个订阅/发布系统,是不是。
Znode更改是与znode相关的数据的修改或znode的子项中的更改。只触发一次watches。如果客户端想要再次通知,则必须通过另一个读取操作来完成。当连接会话过期时,客户端将与服务器断开连接,相关的watches也将被删除。
下面说完简单的,来说点复杂的部分。
几个特性先了解下:
- One-time trigger 一次watch时间只会被触发一遍,如果节点再次发生变化,除非之前有重新设置过watches,不然不会收到通知;
- Sent to Client 当watch的对象状态发生改变时,将会触发此对象上watch所对应的事件。watch事件将被异步地发送给客户端,并且ZooKeeper为watch机制提供了有序的一致性保证(Ordering guarantee)。
- The data for which the watch was set 发送给客户端的数据信息,实际上就是你这个watch监视的类型,见下文介绍
Zookeeper的Watches 分为两种,数据监听器(Data Watches)和子节点监听器(Children Watches)。即你可以对某个节点的Data设置watches,也可以对某个子节点设置watches。
可以看下Zookeeper Java 客户端 Zkclient
中的设置watches的代码:
// listener 监听器
// path 节点路径
// 子节点监听器
private List<String> addTargetChildListener(String path, IZkChildListener listener) {
return client.subscribeChildChanges(path, listener);
}
// 节点数据的监听器
public void addChildDataListener(String path, IZkDataListener listener) {
try {
// 递归创建节点
client.subscribeDataChanges(path, listener);
} catch (ZkNodeExistsException e) {
}
}
作为开发者,需要知道监控节点的什么操作会触发你设置的watches。
- 一个成功的setData操作将触发Znode的数据watches
- 一个成功的create操作将触发Znode的数据watches以及子节点watches
- 一个成功的delete操作将触发Znode的数据watches和子节点watches
再看下ZkClient中的数据监听器接口IZkDataListener
public interface IZkDataListener {
// 监控节点数据更新的时候会触发 这段逻辑
public void handleDataChange(String dataPath, Object data) throws Exception;
// 监控节点被删除的时候会触发 这段逻辑
public void handleDataDeleted(String dataPath) throws Exception;
}
再看下ZkClient中的子节点监听器接口IZkChildListener
public interface IZkChildListener {
/**
* Called when the children of the given path changed.
* 监控节点的子节点列表改变时会触发这段逻辑
*
* @param parentPath
* The parent path
* @param currentChilds
* The children or null if the root node (parent path) was deleted.
* @throws Exception
*/
public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception;
}
实际上看到这就能联想到,Zookeeper是可以当做分布式配置中心来使用的,只不过你需要自己扩展他异步通知节点数据变化之后的逻辑,更新你的配置。在后面的章节会更新相关demo。
关于Watches 详细介绍可以参考官网的介绍:
ZooKeeper Watches
六、 总结
本章内容算是Zookeeper系列的开篇,介绍了Zookeeper的几个基础概念,并且给出了相关实例,助于理解。
现在我们再回过头来看看Zookeeper的特性:
① 顺序一致性
从同一个客户端发起的事务请求,最终将会严格按照其发起顺序被应用到ZooKeeper中。② 原子性
所有事务请求的结果在集群中所有机器上的应用情况是一致的,也就是说要么整个集群所有集群都成功应用了某一个事务,要么都没有应用,一定不会出现集群中部分机器应用了该事务,而另外一部分没有应用的情况。③ 单一视图
无论客户端连接的是哪个ZooKeeper服务器,其看到的服务端数据模型都是一致的。④ 可靠性
一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会被一直保留下来,除非有另一个事务又对其进行了变更。⑤ 实时性
通常人们看到实时性的第一反应是,一旦一个事务被成功应用,那么客户端能够立即从服务端上读取到这个事务变更后的最新数据状态。这里需要注意的是,ZooKeeper仅仅保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。
今天的内容中,顺序一致性是通过ZXid来实现的,全局唯一,顺序递增,同一个session中请求是FIFO的;可靠性的描述也可以通过今天的知识进行理解,一次事务的应用,服务端状态的变更会以Zxid、Znode数据版本、数据、节点路径的形式保存下来。剩下的几种特性是怎么实现的,在学习完Zookeeper集群相关的内容之后应该就能理解。
本篇文章中借鉴了网上几篇优秀的文章,并且结合了我本人一些思考和实践。希望能对你学习了解Zookeeper起到一些帮助。
下一章,我会介绍Zookeeper集群方面的知识,CAP
理论在Zookeeper中的实践,以及如何搭建Zookeeper的集群。
参考
[1] https://zookeeper.apache.org/... 官方文档(强烈推荐)
[2] https://www.cnblogs.com/sundd... 作者应该是对官方文档有比较深的了解,我发现他的文章的脉络和官网有很相似的地方。写的非常好
[3] https://www.jianshu.com/p/a17... 作者对Zookeeper做了一个易懂的总体介绍
[4] https://www.w3cschool.cn/zook... w3cSchool tutorial
以上是关于学习zookeeper—基础的主要内容,如果未能解决你的问题,请参考以下文章
[转帖]Zookeeper学习系列 教会你Zookeeper的一些基础概念