前言
Zookeeper的客户端命令详解
文章目录
- 前言
- 一、节点信息
- 二、节点类型
- 三、节点操作
- 四、监听器介绍和原理(重要)
-
- 4.1 监听操作
- 4.2 监听原理
- 4.3 IDEA 客户端操作Zookeeper
- 4.4 写数据原理
一、节点信息
ls -s /
:相应节点的详细信息
[zk: centos1(CONNECTED) 5] ls -s /
[zookeeper]cZxid = 0x0 # znode被创建时的事务ID
ctime = Thu Jan 01 08:00:00 CST 1970 # znode被创建时的时间
mZxid = 0x0 # znode最后更新的事务ID
mtime = Thu Jan 01 08:00:00 CST 1970 # znode最后修改的时间
pZxid = 0x0 # 最后更新的子节点
cversion = -1 # 子节点被修改的次数
dataVersion = 0 # znode数据变化版本号
aclVersion = 0 # 访问控制列表的变化号
ephemeralOwner = 0x0 # 如果是临时节点,这个对应znode拥有者的sessionID,如果不是临时节点对应0
dataLength = 0 # znode的数据长度
numChildren = 1 # znode的子节点数量
二、节点类型
Zookeeper中的节点包含临时节点和持久节点。
- 持久节点包括:持久化目录节点、持久化顺序编号目录节点。断开连接后,创建的节点不删除;
- 临时节点包括:临时目录节点、临时顺序编号目录节点。断开连接后,创建的节点删除;
说明: 在创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护。这样使得在分布式系统中,可以利用数据号为所有事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序。
三、节点操作
create 节点路径 节点描述
:创建永久节点(默认);
create -e 节点路径 节点描述
:创建临时节点;
create -s 节点路径 节点描述
:创建带序号的永久节点;
create -s -e 节点路径 节点描述
:创建带序号的临时节点;
set 节点路径 节点描述
:修改节点信息;
ls [-s] [-R] [-w] 节点路径
:获取节点或者节点下面所有节点的信息;
delete 节点路径
:删除一个节点
deleteall 节点路径
:删除一个路径上的所有节点
``
四、监听器介绍和原理(重要)
4.1 监听操作
- 监听节点的值变化
:给指定路径添加监听。注意监听注册一次就只能使用一次,其余修改不会再收到通知,必须重新注册。get -w 节点路径
- 监听节点的子节点变化(路径变化)
:监听指定节点的子节点变化。同上ls -w 节点路径
4.2 监听原理
- 客户端首先创建一个
线程;main()
- 在
线程中创建Zookeeper客户端,这时候会创建两个线程,一个main()
负责监听;一个listener
负责网络连接通信;connect
- 通过
线程将注册的监听事件发送给Zookeeper;connect
- 将注册事件存储进服务器端的Zookeeper注册监听器列表中;
- Zookeeper如果监听到数据或者路径有变化就将这个消息发送给
线程;listener
-
线程内部调用了listener
方法来处理。process()
4.3 IDEA 客户端操作Zookeeper
- 环境搭建
<dependencies>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<!-- log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.13.3</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
- 日志配置
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c]- %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
- 创建并操纵Zookeeper客户端
public class zkClient {
private String hostName="192.168.1.6:2181,192.168.1.7:2181,192.168.1.8:2181";
private ZooKeeper zkCli = null;
/**
* 建立连接
* public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher) throws IOException {
* this(connectString, sessionTimeout, watcher, false);
* }
* 1.连接的服务器名 2.超时时间 3.监视器
*/
@BeforeEach
@Test
public void init() throws Exception {
System.out.println("初始化.................");
zkCli = new ZooKeeper(hostName, 60000, new Watcher() {
public void process(WatchedEvent watchedEvent) {
List<String> children = null;
try {
children = zkCli.getChildren("/", true);
System.out.println("---------------------------");
for (String child : children) {
System.out.println(child);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
// zkCli.create("/xuexi","好好学习".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
/**
* public String create(String path, byte[] data, List<ACL> acl, CreateMode createMode)
* 1.路径 2.内容 3.访问权限 4.创建模式
* 创建子节点
*/
@Test
public void createChildren() throws KeeperException, InterruptedException {
zkCli.create("/xuexi","好好学习".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zkCli.create("/xuexi/昨天","摸了一天鱼".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zkCli.create("/xuexi/今天","认真学习".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zkCli.create("/xuexi/明天","调整好作息,认真对待".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
/**
* 1.List<String> getChildren(String path, Watcher watcher):自定义Watcher
* 2.List<String> getChildren(String path, boolean watch):使用初始化连接时的Watcher
* 监听子节点
* 每使用一次下一次都需要进行注册!!!
*/
@Test
public void getChildren() throws KeeperException, InterruptedException {
List<String> children = zkCli.getChildren("/", true);
System.out.println("---------------------------");
for (String child : children) {
System.out.println(child);
}
}
4.4 写数据原理
- 写流程将写请求直接发送给Leader节点 如图,Client 将请求发送给
,Leader写完数据后将数据同步给ZK Server Leader
。当集群中有半数以上的节点写完数据后,就将结果返回给客户端,因此此时直接由ZK Server Follower1
将数据返回给ZK Server Leader
。之后再由Client
同步数据到ZK Server Leader
。ZK Server Follower2
- 写流程将写请求直接发送给Follower节点 Follower接收到节点数据后将数据发送给Leader,然后当前Follower和Leader同时开始同步数据,Leader还需要将数据发送给其他Follower节点进行数据同步,最终集群中有半数以上的节点同步完数据时就返回响应给客户端。