实际应用中, zookeeper
都是使用集群方式安装, 但本文只是入门级演示, 故使用单机版演示.
集群安装可参考完整版视频教程: 【尚硅谷】大数据技术之Zookeeper 3.5.7版本教程
在官网Release界面下载最新稳定版本
进入后得到http
方式的下载地址:https://dlcdn.apache.org/zookeeper/zookeeper-3.7.1/apache-zookeeper-3.7.1-bin.tar.gz
#!/bin/bash
ZK_ROOT_PATH=/opt
curl -o ${ZK_ROOT_PATH}/zk.tar.gz https://dlcdn.apache.org/zookeeper/zookeeper-3.7.1/apache-zookeeper-3.7.1-bin.tar.gz
tar zxvf ${ZK_ROOT_PATH}/zk.tar.gz -C ${ZK_ROOT_PATH}/
mv ${ZK_ROOT_PATH}/apache-zookeeper-3.7.1-bin ${ZK_ROOT_PATH}/zk
此时ZK_HOME
指向了${ZK_ROOT_PATH}/zk
, 为了方便管理, 可以在环境变量中设置, 同时将其脚本追加至PATH
:
vi ~/.bash_profile
追加PATH
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
ZK_ROOT_PATH=/opt
ZK_HOME=${ZK_ROOT_PATH}/zk
PATH=$PATH:${ZK_HOME}/bin:$HOME/.local/bin:$HOME/bin
export PATH
export ZK_HOME
测试which zkServer.sh
zookeeper
默认提供了样例, 位于conf/zoo_sample.cfg
, 我们将其重命名为zoo.cfg
主要参数
参数 | 描述 | 备注 |
---|---|---|
tickTime | 通信心跳时间,Zookeeper服务器与客户端心跳时间,单位毫秒 | |
initLimit | LF初始通信时限, Leader和Follower初始连接时能容忍的最多心跳数(tickTime的数量) | LF: Leader Follower |
syncLimit | LF同步通信时限, Leader和Follower之间通信时间如果超过syncLimit * tickTime,Leader认为Follwer死掉,从服务器列表中删除Follwer。 | |
dataDir | 保存Zookeeper中的数据 | 默认的tmp目录,容易被Linux系统定期删除,所以一般不用默认的tmp目录。 |
clientPort | 客户端连接端口,通常不做修改。 |
一般只需修改dataDir
, 比如改为${ZK_HOME}/data
mv ${ZK_HOME}/conf/zoo_sample.cfg ${ZK_HOME}/conf/zoo.cfg
sudo mkdir $ZK_HOME/data
sed -e 's/dataDir.*/dataDir=${ZK_HOME}\/data/g' -i ${ZK_HOME}/conf/zoo.cfg
# 授予当前用户所有权
sudo chown -R $(whoami):$(whoami) $ZK_HOME
此时安装已完成, 可以使用zkServer.sh
进行操作:
# 启动
zkServer.sh start
# 查看状态
zkServer.sh stat
可以得到输出:
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zk/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone
这表明启动成功了, 并且模式为standalone
.
zkCli.sh
如果远程连接, 可以使用server
指定:
# zkCli.sh -server 10.99.181.22:2181
zkCli.sh -server ${host}:${ip}
客户端完整命令比较多, 这里列举几个比较常用的
命令 | 描述 | 备注 |
---|---|---|
help | 显示所有操作命令 | |
ls path | 使用 ls 命令来查看当前 znode 的子节点 [可监听] -w 监听子节点变化 -s 附加次级信息 | ls / |
create | 普通创建 -s 含有序列 -e 临时(重启或者超时消失) | |
get path | 获得节点的值 [可监听] -w 监听节点内容变化 -s 附加次级信息 | |
set | 设置节点的具体值 | |
stat | 查看节点状态 | |
delete | 删除节点 | |
deleteall | 递归删除节点 |
使用ls -s
可以查看节点详细信息, 比如:
[zk: localhost:2181(CONNECTED) 3] ls -s /
[zookeeper]
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
此处涉及属性描述如下:
属性 | 描述 | 备注 |
---|---|---|
czxid | 创建节点的事务 zxid | 每次修改 ZooKeeper 状态都会产生一个 ZooKeeper 事务 ID。 事务 ID 是 ZooKeeper 中所有修改总的次序。 每次修改都有唯一的 zxid,如果 zxid1 小于 zxid2, 那么 zxid1 在 zxid2 之前发生。 |
ctime | znode 被创建的毫秒数(从 1970 年开始) | |
mzxid | znode 最后更新的事务 zxid | |
mtime | znode 最后修改的毫秒数(从 1970 年开始) | |
pZxid | znode 最后更新的子节点 zxid | |
cversion | znode 子节点变化号,znode 子节点修改次数 | |
dataversion | znode 数据变化号 | |
aclVersion | znode 访问控制列表的变化号 | |
ephemeralOwner | 如果是临时节点,这个是 znode 拥有者的 session id。如果不是临时节点则是 0。 | |
dataLength | znode 的数据长度 | |
numChildren | znode 子节点数量 |
说明:创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护
注意:在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序
默认情况下, create
命令不带任何参数就是创建不带序号持久节点(目录), 如果需要创建临时的, 则加上-e
选项, 带序号则加上-s
选项:
# 创建不带序号持久化目录/sanguo
[zk: localhost:2181(CONNECTED) 5] create /sanguo "diaochan"
Created /sanguo
# 创建不带序号临时目录
[zk: localhost:2181(CONNECTED) 24] create -e /sanguo/shu "刘备"
Created /sanguo/shu
[zk: localhost:2181(CONNECTED) 25] create -e /sanguo/wei "曹操"
Created /sanguo/wei
[zk: localhost:2181(CONNECTED) 26] create -e /sanguo/wu "孙权"
Created /sanguo/wu
# 创建临时带序号目录
[zk: localhost:2181(CONNECTED) 19] create -e -s /sanguo/shu "三顾茅庐"
Created /sanguo/shu0000000001
[zk: localhost:2181(CONNECTED) 20] create -e -s /sanguo/shu "三顾茅庐"
Created /sanguo/shu0000000002
[zk: localhost:2181(CONNECTED) 21] create -e -s /sanguo/shu "三顾茅庐"
Created /sanguo/shu0000000003
[zk: localhost:2181(CONNECTED) 23] get /sanguo/shu0000000001
三顾茅庐
监听原理详解
常见的监听
set /sanguo "diaochan"
# 监听
get -w /sanguo
注意:
注册一次,只能监听一次。想再次监听,需要再次注册。
引入依赖:
maven
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.7.1version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.17.1version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-apiartifactId>
<version>2.17.1version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
java
private static final String connectString = "192.168.83.168:2181";
private static final int sessionTimeout = 1000;
public void init() {
Watcher watcher = watchedEvent -> {
String path = watchedEvent.getPath();
log.error(path);
};
try (ZooKeeper zooKeeper = new ZooKeeper(connectString, sessionTimeout, watcher)) {
byte[] data = zooKeeper.getData("/sanguo", watcher, new Stat());
System.out.println(new String(data, StandardCharsets.UTF_8));
} catch (InterruptedException | IOException | KeeperException e) {
e.printStackTrace();
}
}
如果是多个节点, connectString
中使用,
分割即可, 不要带空格