Zookeeper教程
# Zookeeper 详细教程
# 一、Zookeeper 介绍
# 1.1 什么是 zookeeper
Zookeeper 是一个分布式的、高性能的、开源的分布式系统的协调(Coordination)服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 Hbase 的一个重要的组件。它是一个为分布式应用提供一致性服务的软件。
# 1.2 zookeeper 应用场景
zookeeper 是一个经典的分布式数据一致性解决方案,致力于为分布式应用提供一个高性能,高可用,且具有严格属性访问控制能力的分布式协调存储服务。
- 维护配置信息
- 分布式锁服务
- 集群管理
- 生成分布式唯一 ID
1、维护配置信息
java 编程经常会遇到配置项,比如数据库的 url,schema,user 和 password 等。通常这些配置项我们会放置在配置文件中,在将配置文件放置在服务器上当需要更改配置的时,需要去服务器上修改对应的配置信息文件。但是随着分布式系统的兴起,由于许多服务都需要使用到该配置文件,因此有必须保证该配置服务的高可用性和各台服务器上配置数据的一致性。通常会将配置文件不俗在一个集群上,然而一个集群动辄上前台服务器,此时如果在一台一台服务器逐个的修改配置文件将是非常繁琐的一个操作。因此就需要一种服务,能够高效快速且可靠的完成配置项的更待等操作,并能够保证各个配置项在每一台服务器上的数据一致性。
zookeeper 就可以提供这样一种服务,其使用 Zab 这种一致性协议来保证一致性。现在有很多开源项目使用 zookeeper 来维护配置,比如 hhase 中,客户端就是连接一个 zookeeper,获得必要 hbase 集群的配置信息然后才可以进一步操作。还有开源的消息队列 kafka 中,也是用 zookeeper 来维护 broker 的信息。
2、分布式锁服务
一个集群是一个分布式系统,有多台服务器组成。为了提高并发度和可靠性,多台服务器运行着同一种服务。当多个服务在运行时就需要协调各服务的进度,有时候需要保证当某个服务在进行某个操作时,其他的服务都不能进行该操作,即对该操作进行加锁,如果当前机器挂掉后,并释放 fail over 到其他的机器继续执行该服务。

3、集群管理
一个集群优势会因为各种软硬件故障或者网络故障,出现某种服务器挂掉而被移除集群,而某些服务器加入到集群中的情况,zookeeper 会将这些服务器加入/移出的情况下通知给集群汇总的其他正常工作的服务器,以及时调用存储和计算等任务的分配和执行等。此外 zookeeper 还会对故障的服务器做出诊断并尝试修复。

4、生成分布式唯一 ID
在过去的单库单表型系统中,通常可以使用数据库字段自带的 auto_increment 属性来自动为每条记录生成一个唯一的 ID。但是分库分表后,就无法再依靠数据库的 auto_increatment 属性来唯一标识一条记录了,此时我们就可以用 zookeeper 在分布式环境下生成全局唯一 ID。做法如下:每一个生成一个新 ID 时,创建一个持久顺序节点,创建操作返回的节点序号,及微信 ID,然后把比自己节点小的删除即可。
# 1.3 zookeeper 的设计目标
zookeeper 致力于为分布式应用提供一个高性能,高可用,具有严格顺序访问控制能力的分布式协调服务。
1、高性能
zookeeper 将全量数据存储在内存中,并直接服务与客户端的所有非事务请求,尤其适合用于以读为主的应用场景。
2、高可用
zookeeper 一般以集群的范式对外提供服务,一般 3-5 台机器就可以组成一个可用的 zookeeper 集群,每一台机器都会在内存中维护当前的服务器状态,并且每台机器之间都相互保持着通信。只要集群中超过一旦的机器都在工作,那么这个集群就能够正常对外服务;
3、严格访问数据
对于客户端的每一个更新请求,Zookeeper 都会分配一个全局唯一的递增编号,这个编号反映了所有事物操作的先后顺序。
# 二、Zookeeper 的数据模型
# 2.1 zookeeper 数据结构
Zookeeper 数据模型的结构与 Unix 文件系统很类似,整体上可以看作是一颗树,每一个节点称做一个 ZNode。每一个 Znode 默认能够存储 1MB 的数据,每个 ZNode 都可以通过其路径唯一标识。

如何来描述一个 ZNode 呢?一个 znode 大体上分为 3 部分:
- 节点的数据:即 znode data(节点 path,节点 data 的关系)就像是 java map 中(key,value)的关系
- 节点的子节点 children
- 节点的状态 stat:用来描述当前节点的创建,修改记录,包括 cZxid、ctime 等。
# 2.2 zookeeper 节点类型
zookeeper 中的节点有两种类型,一种是临时节点和永久节点。节点类型在创建是即被确定,并且不能改变。
- 临时节点 :该节点的生命周期依赖于创建他们的回话。一旦回话(Session)结束,临时节点将会被自动删除,当然可以手动的进行删除。虽然每个临时的 ZNode 都会绑定到一个客户端回话,但他们对所有的客户端还是可见的。另外,Zookeeper 的临时节点不允许拥有子节点。
- 持久化节点:该节点的生命周期不依赖于花花,并且只有在客户点显示执行删除操作的时候,他们才能被删除。
# 2.3 zookeeper 单机安装
当前测试系统环境 centos7.3
1.在 centos 中使用 root 用户创建 zookeeper 用户,用户名:zookeeper 密码:zookeeper
useradd zookeeper
passwd zookeeper
2
- zookeeper 底层依赖 jdk,zookeeper 用户登录后,根目录下先进行 jdk 的安装,jdk 使用 jdk-11.0.5
//解压jdk tar -xzvf jdk-11.0.5.tar.gz
3.配置 jdk 环境量
//打开/etc/profile文件
# vim /etc/profile
export JAVA_HOME=/root/apps/jdk-11.0.5
export PATH=$PATH:$JAVA_HOME/bin
//执行profile
#source /etc/profile
2
3
4
5
6
4.zookeeper 使用 zookeeper-3.4.10.tar.gz,上传并解压
//解压zookeeper
tar -xzvf zookeeper-3.4.10.tar.gz
2
5.为 zookeeper 准备配置文件
//进入conf目录
cd /root/apps/zookeeper/zookeeper-3.4.14/conf
//复制配置文件
cp zoo_sample.cfg zoo.cfg
//zookeeper根目录下新建data目录
mkdir data
// vi 修改配置文件中的dataDir
// 此路径用于存储zookeeper中数据的内存快照,及事务日志文件
dataDir=/root/apps/zookeeper/zookeeper-3.4.14/data
2
3
4
5
6
7
8
9

6.zookeeper 启动命令
[root@centos ~]# systemctl stop firewalld #关闭防火墙的命令
[root@centos ~]# zkServer.sh start #启动
[root@centos ~]# zkServer.sh stop #关闭
[root@centos ~]# zkServer.sh status #查看运行状态
启动客户端:
[root@localhost ~]# zkCli.sh //启动客户端
[zk: localhost:2181(CONNECTED) 0] ls / #查看根节点命令
//查看zookeeper进程是否存在
[root@centos zookeeper-3.4.14]# ps -ef | grep zookeeper
2
3
4
5
6
7
8
9
10
# 三、zookeeper 常用的 Shell 命令
# 3.1 新增节点
create [-s] [-e] path data # 其中 -s 为有序节点, -e 临时节点
1.创建持久化节点并写入数据:
create /hadoop "123456"
2.创建持久化有序节,此时创建的节点名为指定节点名+自增序号
//创建一个持久化节点
[zk: localhost:2181(CONNECTED) 1] create /hadoop "123456"
//通过get命令获取该节点的值
[zk: localhost:2181(CONNECTED) 2] get /hadoop
//创建一个有序的节点
[zk: localhost:2181(CONNECTED) 4] create -s /a "aa"
Created /a0000000001
//获取路径的值
[zk: localhost:2181(CONNECTED) 5] get /a0000000001
aa
//创建临时节点并获取值
[zk: localhost:2181(CONNECTED) 1] create -e /tmp "tmp"
Created /tmp
[zk: localhost:2181(CONNECTED) 2] get /tmp
tmp
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

3.创建临时节点,临时节点会在回话过期后被删除;
[zk: localhost:2181(CONNECTED) 1] create -e /tmp "tmp"
Created /tmp
2
3
4.创建临时有序节点,临时节点会在会话过期后被删除:
```xml
[zk: localhost:2181(CONNECTED) 1] create -s -e /tmp "tmp" Created /tmp000000001
##### 3.2 更新节点
```xml
//使用set命令来更新hadoop节点
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345"
//根据版本号来更新节点
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345" 2
2
3
4
5
6
7
8
9
也可以基于版本号来进行更改,此时类似于乐观锁机制,当你传入的数据版本号(dataVersion)和当前节点的数据版本号不符合时,zookeeper 会拒绝本次修改:
# 3.3 删除节点
1.删除节点的命令如下
delete path [version]
和更新节点数据一样,也可以传入版本号,当你传入的数据版本号(dataVersion)和当前节点的数据版本号不符合时,zookeeper 不会执行删除操作。
//根据版本号来删除节点
[zk: localhost:2181(CONNECTED) 1] set /hadoop "345" 2
2
要想删除某个节点及其所有后代节点,可以使用递归删除,命令为 rmr path。
# 3.4 查看节点
get path
[zk: localhost:2181(CONNECTED) 1] get /hadoop
2
[zk: localhost:2181(CONNECTED) 0] create /hadoop2 "hadoop"
Created /hadoop2
[zk: localhost:2181(CONNECTED) 1] get /hadoop2
hadoop
cZxid = 0xb
ctime = Thu May 14 09:06:29 CST 2020
mZxid = 0xb
mtime = Thu May 14 09:06:29 CST 2020
pZxid = 0xb
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 2]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
节点各个属性如下表。起哄一个重要的概念是 Zxid(ZooKeeper Transaction Id),ZooKeeper 节点的每一个更改都具唯一的 Zxid,如果 Zxid1 小于 Zxid2,则 Zxid1 的更改发生在 Zxid2 更改之前。
| 状态属性 | 节点说明 |
|---|---|
| cZxid | 数据节点创建时的事务 ID |
| ctime | 数据节点创建世的时间 |
| mZxid | 数据节点最后一个更新是的事务 ID |
| mtime | 数据节点最后一个跟新时的时间 |
| pZxid | 数据节点的子节点最后一个被修改时的事务 ID |
| cversion | 子节点的更改次数 |
| dataVerion | 节点数据的更改次数 |
| aclVersion | 节点 ACL 的更改次数 |
| ephemeralOwner | 如果节点是临时节点,则表示创建该节点的会话的 SeeesionID;如果是持久节点,则该属性值为 0 |
| dataLength | 数据内容的长度 |
| numChildren | 数据节点当前的子节点个数 |
# 3.5 查看节点状态
可以使用 stat 命令查看节点状态,它的返回值和 get 命令类似,但不会返回节点数据
//使用stat命令来查看节点状态
[zk: localhost:2181(CONNECTED) 0] stat /hadoop
cZxid = 0x4
ctime = Thu May 14 07:56:33 CST 2020
mZxid = 0x4
mtime = Thu May 14 07:56:33 CST 2020
pZxid = 0x4
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 1]
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.6 查看节点列表
查看节点列表有 ls path 和 ls2 path 两个命令,后者是前者的增强。不仅可以查看指定路径下的所有节点,还可以查看当前几点的信息
[zk: localhost:2181(CONNECTED) 5] ls /
[a0000000001, hadoop, zookeeper, tmp, hadoop2]
[zk: localhost:2181(CONNECTED) 6] ls2 /
[a0000000001, hadoop, zookeeper, tmp, hadoop2]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0xb
cversion = 3
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 5
[zk: localhost:2181(CONNECTED) 7]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 3.7 监听器 get path [watch]
使用 get path [watch] 注册的监听器能够在节点内容发生改变的时候,向客户点发出通知。需要注意的是 zookeeper 的触发器是一次性的(One-time trigger),触发一次后就会立即失效。
[zk: localhost:2181(CONNECTED) 8] get /hadoop watch
123456
cZxid = 0x4
ctime = Thu May 14 07:56:33 CST 2020
mZxid = 0x4
mtime = Thu May 14 07:56:33 CST 2020
pZxid = 0x4
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 9]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/hadoop
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3.8 监听器 stat path [watch]
使用 stat path [watch] 注册的监听器能够在节点抓哪个台发生改变的时候,向客户点发出通知。
[zk: localhost:2181(CONNECTED) 1] stat /hadoop watch
cZxid = 0x4
ctime = Thu May 14 07:56:33 CST 2020
mZxid = 0xf
mtime = Thu May 14 10:01:04 CST 2020
pZxid = 0x4
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 2]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/hadoop
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 4.9 监听器 ls\ls2 path [watch]
使用 ls path [watch] 或者 ls2 path [watch] 注册的监听器能够监听该节点下所有子节点的增加和删除操作。
# 四、zookeeper 权限控制
# 4.1 概述
zookeeper 类似于文件系统,client 可以创建节点,更新节点,删除节点,那么如何做到节点的权限的控制呢?zookeeper 的 access control list 访问控制列表可以自耦到这一点。
acl 权限控制,使用 scheme:id:permission 来表示,主要涵盖 3 个方面:
权限模式(scheme):授权的策略
授权对象(id):授权的对象
权限(permission):授予的权限
其特性如下:
zookeeper 的权限控制是基于每个 znode 节点的,需要对每个节点设置权限
每个 znode 支持设置多种权限控制方案和多个权限
子节点不会继承父节点的权限,客户点无权访问某个节点,但可能可以访问他的子节点
setAcl /test2 ip:192.168.60.130:rewda //将节点权限设置为Ip:192.168.60.130的客户端可以对节点进行增、删、该、查、权限管理
# 4.2 权限模式
采用何种方式授权
| 方案 | 描述 |
|---|---|
| world | 只有一个用户:anyone,代表登录 zooleeper 所有人(默认) |
| ip | 对客户端使用 ip 地址认证 |
| auth | 使用已添加认证的用户认证 |
| digest | 使用“用户名:密码”方式认证 |
# 4.3 授权的对象
给谁授权
授权对象 ID 是指,权限赋予的实体例如:ip 地址或用户。
# 4.4 授予的权限
授予什么权限
create、delete、read、writer、admin 也就是增、删、改、查、管理权限,这 5 中权限简写为 cdrwa、注意:这 5 中权限中,delete 是指对子节点的删除权限,其他 4 种权限值对自身节点的权限操作。
| 权限 | ACL 简写 | 描述 |
|---|---|---|
| create | c | 可以创建子节点 |
| delete | d | 可以删除子节点(仅下一级节点) |
| read | r | 可以读取节点数据及显示子节点列表 |
| write | w | 可以设置节点数据 |
| admin | a | 可以设置节点访问控制列表权限 |
# 4.5 授权的相关命令
| 命令 | 使用方式 | 描述 |
|---|---|---|
| getAcl | getAcl<path> | 读取 ACL 权限 |
| setAcl | setAcl<path><acl> | 设置 ACL 权限 |
| addauth | addauth<scheme><auth> | 添加认证用户 |
# 4.6 案例
world 授权模式:
命令
setAcl <path> world:anyone:<acl> setAcl /hadoop world:anyone:cdrwa1
2案例
[zk: localhost:2181(CONNECTED) 2] getAcl /hadoop 'world,'anyone #world方式对所有用户进行授权 : cdrwa #增、删、改、查、管理 [zk: localhost:2181(CONNECTED) 3]1
2
3
4IP 授权模式
命令
#需要两台机器来进行连接 192.168.60.129 192.168.60.130 #使用 192.168.60.129 登录zookeeper zkCli.sh -server 192.168.60.130 #使用本机 192.168.60.130 zookeeper zkCli.sh -server 192.168.60.1301
2
3
4
5
Auth 授权模式
命令
addauth digest <user>:<password> #添加认证用户 setAcl <path>auth:<user>:<acl>1
2案例
[zk: localhost:2181(CONNECTED) 0] create /hadoop3 "hadoop3"
Created /hadoop3
[zk: localhost:2181(CONNECTED) 1] getAcl /hadoop3
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 2] addauth digest tyx:123
[zk: localhost:2181(CONNECTED) 3] setAcl /hadoop3 auth:tyx:cdrwa
cZxid = 0x16
ctime = Thu May 14 20:29:34 CST 2020
mZxid = 0x16
mtime = Thu May 14 20:29:34 CST 2020
pZxid = 0x16
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0
[zk: localhost:2181(CONNECTED) 7] getAcl /hadoop3
'digest,'tyx:nSk0WYb+XoISHNhIQiQ1BGsZHjE=
: cdrwa
[zk: localhost:2181(CONNECTED) 8]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Digest 授权模式
命令
setAcl <path> digest:<user>:<password>:<acl>1这里的密码是经过 SHA1 及 BASE64 处理的密文,在 SHEEL 中可以通过命令计算:
echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base641先来计算一个密文
echo -n tyx:123 | openssl dgst -binary -sha1 | openssl base64 #得到的密文 [root@centos zookeeper-3.4.14]# echo -n tyx:123 | openssl dgst -binary -sha1 | openssl base64 nSk0WYb+XoISHNhIQiQ1BGsZHjE=1
2
3
4案例:
[zk: localhost:2181(CONNECTED) 8] create /hadoop4 "hadoop4" Created /hadoop4 [zk: localhost:2181(CONNECTED) 10] getAcl /hadoop4 'world,'anyone : cdrwa //使用digest进行授权 [zk: localhost:2181(CONNECTED) 11] setAcl /hadoop4 digest:tyx:nSk0WYb+XoISHNhIQiQ1BGsZHjE=:cdrwa //该节点的权限 [zk: localhost:2181(CONNECTED) 13] getAcl /hadoop4 'digest,'tyx:nSk0WYb+XoISHNhIQiQ1BGsZHjE= : cdrwa //没有权限 [zk: localhost:2181(CONNECTED) 0] get /hadoop4 Authentication is not valid : /hadoop4 //添加授权用户 [zk: localhost:2181(CONNECTED) 1] addauth digest tyx:123 [zk: localhost:2181(CONNECTED) 2] get /hadoop4 hadoop4 cZxid = 0x19 ctime = Thu May 14 21:12:46 CST 2020 mZxid = 0x19 mtime = Thu May 14 21:12:46 CST 2020 pZxid = 0x19 cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 7 numChildren = 01
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31多种密室授权:
同一个节点可以同时使用多种模式授权
[zk: localhost:2181(CONNECTED) 8] create /hadoop4 "hadoop4" Created /hadoop4 //添加认证用户 [zk: localhost:2181(CONNECTED) 8] addauth digest itcast:123456 [zk: localhost:2181(CONNECTED) 8] setAcl /hadoop4 ip:192.168.60.129:cdrwa,auth:tyx:123:cdrwa,digest:tyx:nSk0WYb+XoISHNhIQiQ1BGsZHjE=:cdrwa1
2
3
4
5
# 4.7 acl 超级管理员
zookeeper 的权限管理模式有一种叫做 super,该模式提供一个超管,可以方阿斌的访问任何权限的节点
假设这个超管是:super:admin,需要先为超管生成密码的密文
echo -n super:admin | openssl dgst -binary -sha1 | openssl base64
那么打开 zookeeper 目录下的/bin/zkServer.sh 服务器脚本,找到如下一行:

之后启动 zookeeper,输入如下的命令添加权限
addauth digest super:admin #添加认证用户
# 五、zookeeper javaAPI
znode 是 zookeeper 集合的核心组件,zookeeper API 提供了一小组方法使用 zookeeper 集合来操作 znode 所有的细节。
客户端用该遵循以下步骤,与 zookeeper 服务器进行清洗和干净的交互。
- 连接到 zookeeper 服务器。zookeeper 服务器为客户端分配回话 ID。
- 定期向服务器发送心跳。否则,zookeeper 服务器将过期回话 ID,客户端需要重新连接。
- 只要回话 ID 处于活动状态,就可以获取/设置 znode。
- 所有任务完成后,断开与 zookeeper 服务器的连接。如果客户端长时间不活动,则 zookeeper 服务器将自动断开客户端。
# 5.1 连接到 zookeeper
Zookeeper(String connectionString,int sessionTimeout,Watcher watcher)
- connectionString -zookeeper 主机
- sessionTimeout - 回话超时(一毫秒为单位)
- watcher -实现“监视器”对象。zookeeper 集合通过监视器对象返回连接状态。
package com.example.springcloud.controller;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @author papi
* @data 2020/5/1
*/
public class ZookeeperTest {
public static void main(String[] args) {
try {
CountDownLatch countDownLatch = new CountDownLatch(1);
//arg1:服务器和端口号
//arg2: 客户端和服务器之间的会话超时时间
//arg3: 监视器对象
ZooKeeper zooKeeper = new ZooKeeper("192.168.90.108:2181", 5000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
System.out.println("连接成功");
//通知主线不要去等待了
countDownLatch.countDown();
}
}
});
//主线程阻塞等待连接对象
countDownLatch.await();
//获取zookeeper的session会话编号
System.out.println(zooKeeper.getSessionId());
zooKeeper.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 5.2 新增节点
//同步方式
create(String path, byte[] data, List<Acl> acl, CreateMode createMode)
//异步方式
create(String path, byte[] data, List<Acl> acl, CreateMode createMode, AsyncCallback.StringCallback callBack,Object ctx)
2
3
4
- path -znode 路径。例如,/node1 /node1/node11
- data -要存储的指定 znode 路径中的数据
- acl - 要创建的节点的访问控制列表。zookeeper API 提供了一个静态接口ZooDefs.Ids 来获取一些基本的 acl 列表。例如,Zoodefs.Ids.OPEN_ACL_USERAFE 返回发开 znode 的 acl 列表。
- createMode -节点的类型,这是一个枚举。
- callBack -异步回调接口
package com.example.springcloud.controller;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* @author papi
* @data 2020/5/15
*/
public class ZookeeperTest {
public static void main(String[] args) {
try {
CountDownLatch countDownLatch = new CountDownLatch(1);
//arg1:服务器和端口号
//arg2: 客户端和服务器之间的会话超时时间
//arg3: 监视器对象
ZooKeeper zooKeeper = new ZooKeeper("192.168.90.108:2181", 5000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
System.out.println("连接成功");
//通知主线不要去等待了
countDownLatch.countDown();
}
}
});
//主线程阻塞等待连接对象
countDownLatch.await();
//获取zookeeper的session会话编号
System.out.println(zooKeeper.getSessionId());
zooKeeper.create("/hadoop7","hadoop7".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
//ZooDefs.Ids.READ_ACL_UNSAFE world:anyone:r
zooKeeper.create("/hadoop8", "hadoop8".getBytes(), ZooDefs.Ids.READ_ACL_UNSAFE, CreateMode.PERSISTENT );
//world 模式
//权限列表
List<ACL> list = new ArrayList<>();
Id id = new Id();
id.setScheme("world");
id.setId("anyone");
list.add(new ACL(ZooDefs.Perms.READ, id));
list.add(new ACL(ZooDefs.Perms.WRITE, id));
zooKeeper.create("/hadoop9", "hadoop9".getBytes(), list, CreateMode.PERSISTENT );
//IP授权模式
List<ACL> acls = new ArrayList<>();
//授权模式和授权对象
Id id1 = new Id("ip", "192.168.60.130");
acls.add(new ACL(ZooDefs.Perms.ALL, id1));
zooKeeper.create("/hadoop10", "hadoop10".getBytes(), acls, CreateMode.PERSISTENT);
//使用auth模式进行授权
zooKeeper.addAuthInfo("digest","tyx:123".getBytes());
zooKeeper.create("/hadoop11", "hadoop11".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL,CreateMode.PERSISTENT);
//使用auth模式进行授权,只读的模式
zooKeeper.addAuthInfo("digest","tyx:123".getBytes());
List<ACL> acls2 = new ArrayList<>();
Id id2 = new Id("auth", "tyx");
acls.add(new ACL(ZooDefs.Perms.READ, id1));
zooKeeper.create("/hadoop12", "hadoop12".getBytes(), acls2,CreateMode.PERSISTENT);
//使用digest模式进行授权
List<ACL> acls3 = new ArrayList<>();
Id id3 = new Id("digest", "tyx:adkalfjasncasaKJHG=");
acls.add(new ACL(ZooDefs.Perms.ALL, id3));
zooKeeper.create("/hadoop13", "hadoop13".getBytes(), acls3,CreateMode.PERSISTENT);
//持久化有序节点
zooKeeper.create("/hadoop14", "hadoop14".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL,CreateMode.PERSISTENT_SEQUENTIAL);
//临时节点
zooKeeper.create("/hadoop15", "hadoop15".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL,CreateMode.EPHEMERAL);
//临时顺序节点
zooKeeper.create("/hadoop16", "hadoop16".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL,CreateMode.EPHEMERAL_SEQUENTIAL);
//异步创建节点
zooKeeper.create("/hadoop16", "hadoop16".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT, new AsyncCallback.StringCallback() {
@Override
public void processResult(int i, String s, Object o, String s1) {
//0代表创建成功
System.out.println(i);
//节点的路径
System.out.println(s);
//节点的路径
System.out.println(o);
//上下文参数
System.out.println(s1);
}
},"I am context");
zooKeeper.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# 5.3 更新节点
//同步方式
setData(String path,byte[] data, int version)
//异步方式
setData(String path, byte[] data, int version, AsyncCallback.StatCallback callBack, Object ctx)
2
3
4
- path -znode 路径
- data -要存储在指定 znode 路径中的数据。
- version -znode 的当前版本号。每当数据更改时,Zookeeper 会更新 znode 的版本号。
- callBack -异步回调接口
- ctx 传递上下文参数
# 5.4 删除节点
//同步方式
delete(String path, int version)
//异步方式
delete(String path, int version, AsyncCallback.VoidCallback callBack, Object ctx)
2
3
4
- path -znode 路径
- version -znode 的当前版本
- callBack -异步回调接口
- ctx -传递上下文参数
案例
//arg1:删除节点的节点路径
//arg2:数据版本信息 -1代表删除节点时不考虑节点版本信息
zooKeeper.delete("/delete/node1", -1);
delete(String path, int version, AsyncCallback.VoidCallback callBack, Object ctx)
2
3
4
# 5.5 查看节点
//同步方式
getData(String path, boolean b, Stat stat)
//异步方式
getData(String path, boolean b, AsyncCallback.DataCallback callBack, Object ctx)
2
3
4
- path -znode 路径
- b -是否使用连接对象中注册的监视器。
- stat -返回 znode 的元数据。
- callBack -异步回调接口
- ctx -传递上下文参数

//异步方式获取

# 5.6 查看子节点
//同步方式
getChildren(String path, boolean b)
//异步方式
getChildren(String path, boolean b, AsyncCallback.ChildrenCallback callBack, Object ctx)
2
3
4
- path -Znode 路径。
- b -是使用连接对象中注册的监视器。
- callBack -异步回调接口。
- ctx -传递上下文参数。
//同步方式
List<String> list = zookeeper.getChildren("/get",false);
for(String str : list){
System.out.println(str);
}
//异步方式
zookeeper.getChildren("/get", false, new AsyncCallback.ChildrenCallback(){
@Override
public void processResult(int rc, String path,Object ctx, List<String> children){
//0代表读取成功
System.out.println(rc);
//子节点路径
System.out.println(path);
//上下文参数对象
System.out.println(ctx);
//子节点信息
for(String str : children){
System.out.println(str);
}
}
},"I am Context")
Thread.sleep(1000);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 6.7 检查节点是否存在
//同步方法
exists(String path, boolean b);
//异步方法
exists(String path, boolean b, AsyncCallback.StatCallBack, Object ctx)
2
3
4
- path -znode 路径
- b -是否使用连接对象中注册的监视器
- callBack -异步回调接口
- ctx -上下文参数
# 六、zookeeper 事件监听机制
# 6.1 watcher 概念
zookeeper 提供了数据的发布/订阅功能,对个订阅者可同时监听某一特定主题对象,当该主题对象的自身状态发生变化时(例如节点内容改变,节点下的子节点列表改变等),会实时,主动通知所有订阅者;
zookeeper 采用了 watcher 机制实现数据的发布/订阅功能。该机制在被订阅对象发生变化时会异步通知客户端,因此客户端不必在 Watcher 注册后轮询阻塞,从而减轻了客户点压力。
watcher 机制实际上与观察者密室类似,也可以看作是一种观察者密室在分布式场景下的实现方式。
# 6.2 wathcer 架构
Watcher 实现由三个部分组成:
- Zookeeper 服务端
- Zookeeper 客户端
- 客户端的 ZKWatchManager 对象
客户端首先将 Watcher 注册到服务端,同时将 Watcher 对象保存到客户端的 Watch 管理器中。当 Zookeeper 服务端监听的数据状态发生变化时,服务端会主动同时客户端,接着客户端的 Watch 管理器会触发相关 Watcher 来回调相应处理逻辑,从而完成整体的数据发布/订阅流程。

# 6.3 wahcher 特性
| 特性 | 说明 |
|---|---|
| 一次性 | wathcer 是一次性的,一旦被触发就会移除,再次使用时需要重新注册 |
| 客户端顺序回调 | watcher 回调是顺序串行化执行的,只有回调后客户端才能看到最新的数据状态。一个 watcher 回调逻辑不用太多,以免影响别的 watcher 执行 |
| 轻量级 | wathcerEvent 是最小的通信单元,结构上只包含通知状态,事件类型和节点路径,并不会告诉数据节点变化前后的具体内容; |
| 时效性 | watcher 只有在当前 session 彻底失效时才会无效,若 session 有效期内快速重连成功。则 wacher 依然存在,然可接收到通知; |
# 6.4 watcher 接口设计
- Wacher 通知状态
KeeperState 是客户端与服务 daunt 连接状态发生变化时对应的通知类型。路径为 org.apache.zookeeper.Watcher.Event.KeeperState,是一个枚举类,其枚举属性如下:
| 枚举属性 | 说明 |
|---|---|
| SyncConnected | 客户端与服务器正常连接时 |
| Disconnected | 客户端与服务器断开连接时 |
| Expired | 回话 session 失效时 |
| AuthFailed | 身份认证失败时 |
Watcher 事件类型(EventType)
EventType 是数据节点(znode)发生变化时对应的通知类型。EventType 变化时 KeeperState 永远处于 SyncConnected 通知状态下;当 KeeperState 发生变化时,EventType 永远为 None。其路径为 org.apache.zookeeper.Watcher.Event.EventType,是一个枚举类,枚举类属性如下:
| 枚举属性 | 说明 |
|---|---|
| None | 无 |
| NodeCreated | Watcher 监听的数据节点被创建时 |
| NodeDeleted | Watcher 监听的数据节点被删除时 |
| NodeDataChanged | Watcher 监听的数据节点内容发生变更时(无论内容数据是否变化) |
| NodeChildrenChanged | Watcher 监听的数据节点的子节点列表发生变更时 |
# 6.5 捕获相应的事件
上面讲到的 zookeeper 客户端连接的状态和 zookeeper 对 znode 节点监听的事件类型,下面我们来将如何建立 zookeeper 的 watcher 监听。在 zookeeper 中采用 zk.getChildren(path,watch)、zk.exists(path,watch),zk.getData(path,watcher,stat)这样的方式为某个 znode 注册监听。
下表以 node-x 节点为例,说明调用的注册方法和监听事件间的关系:
| 注册方式 | Created | ChildrenChanged | Changed | Deleted |
|---|---|---|---|---|
| zk.exists("/node-x",watcher) | 可监控 | 可监控 | 可监控 | |
| zk.getData("/node-x",watcher) | 可监控 | 可监控 | ||
| zk.getChildren("/node-x",watcher) | 可监控 | 可监控 |
# 6.5 注册 watcher 的方法
客户端与服务器的连接状态
KeeperState : 通知状态
SyncConnected:客户端与服务器正常连接时
Disconnected:客户端与服务器断开连接时
Expired:回话session失效时
AuthFailed:身份认证失败时
事件类型为:None
2
3
4
5
6
7
# 6.6 查看节点
//使用连接对象的监听器
getData(String path, boolean b, Stat stat)
//滴定仪监视器
getData(String path, boolean b, Stat stat)
//NodeDeleted:节点删除
//NodeDataChanged:节点内容发生变化
2
3
4
5
6
- path -znode 路径。
- b -是否使用连接对象中注册的监听器。
- w -监视器对象。
- stat - 返回 znode 的元数据
# 七、配置中心案例
工作中有这样一个场景:数据库用户名和密码信息放在一个配置文件中,应用读取该配置文件,配置文件信息放入缓存。
若数据库的用户名和密码改变时候,还需要重新加载缓存,比较麻烦,通过 Zookeeper 可以轻松完成,当数据库发生变化时自动完成缓存同步。
设计思路:
- 连接 zookeeper 服务器
- 读取 zookeeper 中的配置信息,注册 watcher 监听器,存入本地变量
- 当 zookeeper 中的配置信息发生变化时,通过 watcher 的回调方法捕获数据变化事件。
- 重新获取配置信息。
# 八、生成分布式唯一 ID
在过去的单库单表型系统中,通常可以使用数据库字段自带的 auto_increment 属性来自动为每条记录生成一个唯一的 ID。但是分库分表后,就无法再依靠数据库的 auto_increment 属性唯一标识一条记录了。此时我们就可以用 zookeeper 在分布式环境下生成全局唯一 ID。
设计思路:
- 连接 zookeeper 服务器
- 指定路径下生成临时有序节点
- 取序号及为分布式环境下的唯一 ID
# 九、分布式锁
分布式锁有多重实现方式,比如通过数据库,redis 都可以实现。作为分布式协同工具 Zookeeper,当然也有者标准的实现方式。下面介绍在 zookeeper 中如何实现排它锁。
设计思路:
1、每个客户端往/Locks 下创建临时有序节点/Locks/Lock_,创建成功后/Locks 下面会有每个客户端对应的节点。如/Locks/Lock_0000001
2、客户端取得/Locks 下子节点,并进行排序,判断排在最前面的是否为自己,如果自己的锁节点在第一位,代表获取锁成功。
3、如果自己的锁节点不在第一位,则监听自己前一位的锁节点。如果自己锁节点 Lock_000002,那么则监听 Lock_0000001
4、当前一位锁节点(Lock_000000001)对应的客户端执行完成,释放了锁,将会触发监听客户端(Lock_000002)的逻辑
5、监听客户端重新执行第 2 步逻辑,判断自己是否获得了锁;
# 十、zookeeper 集群搭建
单机环境下,jdk、zookeeper 安装完毕,基于一台虚拟机,进行 zookeeper 伪集群搭建,zookeeper 集群中包含 3 个节点,节点对外提供服务端口号分别为 2181,2182,2183
# 10.1 配置 zookeeper 服务器文件
1、基于 zookeeper-3.4.14 复制三分 zookeeper 安装好的服务器文件,目录名称分别为 zookeeper2181、zookeeper2182、zookeeper2183
cp -r zookeeper-3.4.14 zookeeper2181
cp -r zookeeper-3.4.14 zookeeper2182
cp -r zookeeper-3.4.14 zookeeper2183
2
3
2.修改 zookeeper2181 服务器对应配置文件
#服务器对应端口号
clientPort=2181
#数据快照文件所在路径
dataDir=/home/zookeeper/zookeeper2181/data
#集群配置信息
#server.A=B:C:D
#A:是一个数字,表示这个是服务器的编号
#B:是这个服务器的ip地址
#C:Zookeeper服务器之间的通信端口号
#D:Leader选举的端口
server.1=192.168.60.130:2287:3387
server.1=192.168.60.130:2288:3388
server.1=192.168.60.130:2289:3389
2
3
4
5
6
7
8
9
10
11
12
13
- 在上一步 dataDir 指定的目录下,创建 myid 文件,然后在该文件添加上一步 server 配置对应 A 数字。
#zookeeper2181对应的数字为1
#/home/zookeeper/zookeeper2181/data目录下执行命令
echo "1" > myid
2
3
4.zookeeper2182 、zookeeper2183 参照 2,3 不找进行相应配置
5.分别启动三台服务器,检验集群状态
登录命令:
./zkCli.sh -server 192.168.60.130:2181
./zkCli.sh -server 192.168.60.130:2182
./zkCli.sh -server 192.168.60.130:2183
2
3
# 10.2 一致性协议:zab 协议
zab 协议的全称是Zookeeper Atomic Broadcast (zookeeper 原子广播)。zookeeper 是通过 zab 协议来保证分布式事务的最终一致性
基于 zab 协议,zookeeper 集群中的角色主要有一下三类,如下表所示:
| 角色 | 描述 |
|---|---|
| 领导者(leader) | 领导者负责进行投票的发起和决议,更新系统状态 |
| 学习者(Learner) | Follower 用于接受客户请求并向客户端返回结果,在选主过程中参与投票 |
| ObServer 可以接受客户端连接,将写请求转发给 leader 节点。但是 ObServer 不参加投票过程,只同步 leader 的状态。ObServer 的目的是为了扩展系统,提高读取速度 | |
| 客户端(Client) | 请求发起方。 |
zab 广播模式工作原理,通过类似两阶段提交协议的方式解决数据一致性:

- leader 从客户端收到一个写请求
- leader 生成一个新的事务并未这个事务生成一个唯一的 ZXID
- leader 将这个事务提议(propose)发送给所有的 follows 节点
- follower 节点将收到的事务请求加入到历史队列(history queue)中,并发送 ack 给 leader
- 当 leader 收到大多数 follower(半数以上节点)的 ack 消息,leader 会发送 commit 请求
- 当 follower 收到 commit 请求时,从历史队列中将事务请求 commit
# 10.3 zookeeper 的 leader 选举
1、服务器状态
looking:寻找 leader 状态。当服务器处于该状态时,它会认为当前集群中没有 leader,因此需要进入 leader 选举状态。
leading:领导者状态。表明当前服务器角色是 leader。
following:跟随者状态。表明当前服务器角色是 follower。
observing:观察者状态。表明当前服务器角色是 observer。
2、服务器启动时期的 leader 选举
在集群初始化阶段,当有一台服务器 server 启动时,其单独无法进行完成 leader 选举,当第二太服务器 server2 启动时,此时两台机器可以相互通信,每台机器都视图 zhaodaoleader。于是进入 leader 选举过程。选举过程如下:
- 每个 server 发出一个投票。由于是初始情况,server1 和 server2 都会将自己作为 leader 服务器进行投票,没投票会包含所推举的服务器的 myid 和 zxid,使用(myid,zxid(事务 ID))来表示,此时 server1 的投票为(1,0),server2 的投票为(2,0),然后各自将这个投票发给集群中其他机器。
- 集群中的每一台服务器接受来自集群中各个服务器的投票。
- 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行 pk,pk 规则如下
- 优先检查 zxid(事务的编号)。zxid 比较大的服务器优先为 leader。
- 如果 zxid 相同,那么就比较 myid(服务器的编号)。myid 比较大的服务器作为 leader 服务器。
对于 Server1 而言,它的投票是(1,0),接受 Server2 的投票为(2,0),首先会比较两者的 zxid,均为 0,在比较 myid,此时 server2 的 myid 最大,于是更新自己的投票为(2,0),然后重新投票,对于 server2 而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次的投票信息即可。
- 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于 server1、server2 而言,都统计出集群中已经有两台机器接受了(2,0)的投票信息,此时便认为已经选出了 leader。
- 改变服务状态。一旦确定了 leader,每个服务器就会更新自己的状态,如果是 follower,那么久变更为 following,如果是 leader,就变更为 leading。
# 10.4 服务器运行时期的 Leader 选举【zxid:事务 ID】
在 zookeeper 运行期间,leader 与非 leader 服务器各司其职,即便当有非 leader 服务器宕机或新加入,此时也不会影响 leader,但是一旦 leader 服务器挂了,那么这个集群将暂停对外服务,进入新一轮 leader 选举,其过程和启动时期的 Leader 选举过程基本一致。
假设正在运行的 server1、server2、server3 三台服务器,当前 leader 是 server2,若某一时刻 leader 挂了、此时开始 Leader 选举。选举过程如下:
- 变更状态。leader 挂后,剩余的服务器都会将自己的服务状态变更为 looking,然后开始进入 leader 选举过程。
- 每个 server 会发出一个投票。在运行期间,每个服务器上的 zxid 可能不同,此时嘉定 server1 的 ZXID 为 122,server3 的 zxid 为 122,在第一轮投票中,server1 和 server3 都会投自己、产生投票(1,122),(3,122),然后各自将投票发送给集群中的所有机器。
- 接受来自各个服务器的投票。与启动时过程相同。
- 处理投票。与启动时过程相同,此时,server3 将会成为 leader。
- 统计投票。与启动时过程相同。
- 改变服务器的状态。与启动时过程相同。
# 10.5 observer 角色及其配置
observer 角色特点:
不参与集群的 leader 选举
不参与集群中写数据时的 ack 反馈
为了使用 observer 角色,在任何想变成 observer 角色的配置文件中加入如下配置:
peerType=observer
并在所有的 server 的配置文件中,配置成 observer 模式的 server 的哪行配置追加:observer,例如:
server.3=192.168.60.130:2289:3389:observer
# 10.6 zookeeperAPI 连接集群
Zookeeper(String connectionString, int sessionTimeout, Watcher watcher)
- **connectionString ** -zooKeeper 集合主机
- sessionTimeout - 回话超时(以毫秒为单位)。
- watcher - 实现“监视器”界面的对象。Zookeeper 集合通过监视器对象返回连接状态。
# 十一、zookeeper 开源客户端 curator 介绍
- zookeeper 开源客户端 curator 介绍
- zookeeper 四字监控命令
- zookeeper 图形化的客户端工具(Zoolnspector)
- taokeeper 监控工具的使用
# 11.1 curator 简介
curator 是 Netflix 公司开源的一个 zookeeper 客户端,后捐赠给 apache,curator 框架在走哦科普日原生 API 接口上进行了包装,解决了很多 zookeeper 客户端非底层的细节开发。提供了 zookeeper 各种应用场景(比如:分布式锁服务,集群领导选举,共享计数器,缓存机制,分布式队列等)的抽象封装,实现了 Fluent 风格的 API 接口,是最好用,最流行的 zookeeper 的客户端。
原生 zookeeperAPI 的不足:
连接对象异步创建,需要开发人员自行编码等待。
连接没有自动重连超时机制
watcher 一次注册生效一次
不支持递归创建树形节点
curator 特点:
解决 session 会话超时重连
watche 反复注册
简化开发 api
遵循 Fluent 风格的 API
提供了分布式锁服务,共享计数器,缓存机制等机制
# 11.2 zookeeoer 四字监控命令
zookeeper 支持某些特定的四字命令与其他的交互。他们大多数是查询命令,用来获取 zookeeper 服务的当前状态及相关的信息。用户在客户点可以通过 telnet 或 nc 向 zookeeper 提交相应的命令。走哦可额偶尔常用的四字命令见下表:
| 命令 | 描述 |
|---|---|
| conf | 输出相关服务的配置的详细信息。比如端口,zk 数据及日志配置路径,最大连接数,session 超时时间,serverid 等。 |
| cons | 列出所有连接到台服务器的客户端连接/回话的详细信息。包括“接受/发送”的包数量、session id。操作延迟,最后的操作执行等信息。 |
| crst | 重置当前这台服务器所有连接/回话的统计信息 |
| envi | 输出关于服务器的环境详细信息 |
| ruok | 测试服务器的详细信息:接受/发送包数量、连接数、模式(leader/follower)、节点总数、延迟、所有客户端的列表。 |
| srst | 重置 server 状态 |
| wchs | 累出服务器 watches 的简洁信息:连接总数、watching 节点总数和 watches 总数 |
| wchc | 通过 session 分组,累出 watch 的所有节点,它的输出是一个与 watch 相关的回话的节点列表 |
| mntr | 雷虎集群的健康状态。包括“接受/发送”的包数量,操作延迟,当前服务模式(leader/follower)、节点总数,watch 总数,临时节点总数 |
# 11.3 conf 命令
conf:输出相关服务配置的详细信息
shell终端输入:echo conf | nc localhost 2181
| 属性 | 含义 |
|---|---|
| clientPort | 客户端端口号 |
| dataDir | 数据快照文件目录 默认情况下 100000 次事务操作生成一次快照 |
| dataLogDir | 事务日志文件目录,生产环境中放在独立的磁盘上 |
| tickTime | 服务器之间或客户端与服务器至今维持心跳的时间间隔(以毫秒为单位) |
| maxClientCnxns | 最大连接数 |
| minSessionTimeout | 最小 session 超时 minSessionTimeout=tickTime*2 |
| maxSessionTimeout | 最大 session 超时 maxSessionTimeout=tickTime*20 |
| serverId | 服务器编号 |
| initLimit | 集群中的 follower 服务器(F)与 leader 服务器(L)之间初始连接时能容忍的最多心跳数 |
| syncLimit | 集群中的 follower 服务器(F)与 leader 服务器(L)之间请求和答应之间能容忍的最多心跳数 |
| electionAlg | 0:基于 UDP 的 LeaderElection 1:基于 UDP 的 FastLeaderElection 2:基于 UDP 和认证的 FastLeaderElection 3:基于 TCP 的 FastLeaderElection 在 3.4.10 版本中,默认值为 3,另外的三种算法已经被弃用了,并且有计划在之后的版本中将它们彻底铲除而不再支持。 |
| electionPort | 选举端口 |
| quorumPort | 数据通信端口 |
| peerType | 是否为观察者 1 为观察者 |
# 11.4 cons 命令
cons:列出所有连接到这台服务器的客户端连接/回话的详细信息
echo cons | nc localhost 2181
| 属性 | 含义 |
|---|---|
| ip | IP 地址 |
| port | 端口号 |
| queued | 等待被处理的请求数,请求缓存在队列中 |
| received | 收到的包数 |
| sent | 发送的包数 |
| sid | 回话 id |
| lop | 最后的操作 GETD-读取数据 DELE-删除 CREA-创建数据 |
| est | 连接时间戳 |
| to | 超时时间 |
| lcxid | 当前回话的操作 id |
| lzxid | 最大事务 id |
| llat | 最后/最新 延时 |
| minlat | 最小延时 |
| maxlat | 最大延时 |
| avglat | 平均延时 |
# 11.5 crst 命令
crst:重置当前这台服务器所有连接/绘画的统计信息
shell 终端输入:echo crest | nc localhost 2181
# 11.6 dump 命令
dump:列出未经处理的回话和临时节点
shell 终端输入:echo dump | nc loalhost 21
| 属性 | 含义 |
|---|---|
| session id | znode path(1 对多,处于队列中排队的 session 和临时节点) |
# 11.7 eniv 命令
envi:输出关于服务器的环境详细信息
shell 终端输入:echo envi |nc localhost 2181
| 属性 | 含义 |
|---|---|
| zookeeper.version | 版本 |
| host.name | host 信息 |
| java.version | java 版本 |
| java.vendor | 供应商 |
| java.home | 运行环境所在目录 |
| java.class.path | classpath |
| java.library.path | 第三方库指定非 java 类包的位置(如:dll,so) |
| java.io.tmpdir | 默认的临时文件路径 |
| java.compiler | JIL 编译器的名称 |
| os.name | Linux |
| os.arch | amd64 |
| os.version | XXXXXXX |
| user.name | zookeeper |
| user.home | /home/zookeeper |
| user.dir | /home/zookeeper/zookeeper2181/bin |
# 11.8 ruok 命令
ruok:测试服务是否处于正确运行状态
echo ruok | nv 192.168.60.120 2181

# 11.9 stat 命令
stat:输出服务器的详细信息与 srvr 相似,但是多了每个连接的回话信息
shell 终端输入:echo stat | nc localhost 2181
| 属性 | 含义 |
|---|---|
| Zookeeper version | 版本 |
| Latency min/avg/max | 延时 |
| Received | 收包 |
| Sent | 发包 |
| Connections | 连接数 |
| OutStanding | 堆积数 |
| Zxid | 最大事务 id |
| Mode | 服务器角色 |
| Node count | 节点数 |
# 11.10 srst 命令
srst:重置 server 状态
shell终端输入:schoolsrst | nc localhost 2181
# 11.11 wchs 命令
wchs:累出服务器 watches 的简洁信息
shell终端输入:echo wchs | nc localhost 2181
| 属性 | 含义 |
|---|---|
| connectsions | 连接数 |
| watch-paths | watch 节点数 |
| watchers | watcher 数量 |
# 11.12 wchc 命令
wchc:通过 session 分组,累出 watch 的所有节点,它的输出的是一个与 watch 相关的回话的节点列表问题:
问题:
wchc is not executed because it is not in the whiltelist
解决方法:
#修改启动指令 zkServer.sh
#注意找到这个信息
else
echo "JMX disabled by user request" > & 2
ZOOMAIN = "org.apache.zookeeper.server.quorum.QuorumPeerMain"
fi
# 添加如下信息
ZOOMAIN = "-Dzookeeper.4lw.commands.whitelist=*${ZOOMAIN}"
2
3
4
5
6
7
8
9
shell 终端输入:echo wchc | nc localhost 2181
# 11.13 wchp 命令
查看服务上有多少个节点;
wchp:通过路径分组,列出所有的 watch 的 session id 信息
问题:
wchp is not executer beacues it is not in the whitelist
解决方法:
#修改启动指令 zkServer.sh
#注意找到这个信息
else
echo "JMX disabled by user request" > & 2
ZOOMAIN = "org.apache.zookeeper.server.quorum.QuorumPeerMain"
fi
# 添加如下信息
ZOOMAIN = "-Dzookeeper.4lw.commands.whitelist=*${ZOOMAIN}"
2
3
4
5
6
7
8
9
10
shell 终端输入:echo wchp | nc localhost 2181
# 11.14 mntr 命令
mntr:猎虎服务器的健康状态
| 属性 | 含义 |
|---|---|
| zk_version | 版本 |
| zk_avg_latency | 平均延时 |
| zk_max_latency | 最大延时 |
| zk_min_latency | 最小延时 |
| zk_packets_received | 收包数 |
| zk_num_alive_connections | 连接数 |
| zk_outstanding_requests | 堆积请求数 |
| zk_znode_count | znode 数量 |
| zk_watch_count | watch 数量 |
| zk_ephemreals_count | 临时节点 |
| zk_approximate_data_size | 数据大小 |
| zk_open_file_decriptor_count | 打开的文件描述符数量 |
| zk_max_file_descriptor_count | 最大文件描述数量 |
| zk_server_state | leader/follower 数量 |
shell 终端输入:echo mntr | nc localhost 2181