Zookeeper概念
•Zookeeper 是一个分布式的、开源的分布式应用程序的协调服务。
•Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务。
•Zookeeper 提供的主要功能包括:
•配置管理
•分布式锁
•集群管理
Zookeeper安装与配置
https://blog.csdn.net/qq_41520636/article/details/114959972
ZKClient安装与使用
https://blog.csdn.net/qq_41520636/article/details/115017709
ZooKeeper 命令操作
基本节点
PERSISTENT 持久化节点
服务端关闭和客户端断开连接,节点都能保存。
EPHEMERAL 临时节点 :-e
当客户端断开连接,节点失效。
PERSISTENT_SEQUENTIAL 持久化顺序节点 :-s
只是将持久化节点排序,节点不会丢失。
EPHEMERAL_SEQUENTIAL 临时顺序节点 :-es
只是将临时节点排序,节点失去客户端连接,节点失效。
服务端命令
进入zookeeper安装目录下的bin,启动shell脚步,zkServer.sh脚步启动
•启动 ZooKeeper 服务: ./zkServer.sh start
•查看 ZooKeeper 服务状态: ./zkServer.sh status
•停止 ZooKeeper 服务: ./zkServer.sh stop
•重启 ZooKeeper 服务: ./zkServer.sh restart
客户端命令
•连接ZooKeeper服务端
./zkCli.sh –server ip:port
•断开连接
quit
•查看命令帮助
help
•显示指定目录下节点
ls 目录
•创建节点
create /节点path value
•获取节点值
get /节点path
•设置节点值
set /节点path value
•删除单个节点
delete /节点path
•删除带有子节点的节点
deleteall /节点path
无法一并创建节点,必须创建父节点,才能创建子节点。
当有子节点,delete删除节点失去作用,无法直接删除节点,必须将子节点全部删除后,父节点才能进行删除。
deleteall 可以直接删除全部节点。
客户端命令-创建临时有序节点
•创建临时节点
create -e /节点path value
•创建顺序节点
create -s /节点path value
•查询节点详细信息
ls –s /节点path
•czxid:节点被创建的事务ID
•ctime: 创建时间
•mzxid: 最后一次被更新的事务ID
•mtime: 修改时间
•pzxid:子节点列表最后一次被更新的事务ID
•cversion:子节点的版本号
•dataversion:数据版本号
•aclversion:权限版本号
•ephemeralOwner:用于临时节点,代表临时节点的事务ID,如果为持久节点则为0
•dataLength:节点存储的数据的长度
•numChildren:当前节点的子节点个数
ZooKeeper JavaAPI 操作
pom.xml引入
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!--curator-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
</dependency>
创建连接【命令:./zkCli.sh –server ip:port】
@Test
public void testConnection() {
// 第一种方式
CuratorFramework newClient = CuratorFrameworkFactory.newClient("192.168.135.20:2181",
60 * 1000, 15 * 1000,
new ExponentialBackoffRetry(3000, 10));
// 第二种方式
CuratorFramework client = CuratorFrameworkFactory.builder().
connectString("192.168.135.20:2181") // 服务端
.sessionTimeoutMs(60 * 1000) // session失效时间
.connectionTimeoutMs(15 * 1000) // 连接最大时间
.retryPolicy(new ExponentialBackoffRetry(3000, 10)) // 重试策略
.namespace("hikktn") // 客户端名称
.build();
// 开启连接
client.start();
}
创建节点【命令:create /节点path】
@Test
public void testCreate(){
try {
// 如果没有指定数据,默认将客户端ip作为节点内容
String path = client.create().forPath("/app1");
System.out.println(path);
} catch (Exception e) {
e.printStackTrace();
}
}
创建节点加内容【命令:create /节点path value】
@Test
public void testCreate2(){
try {
// 创建节点和内容
String path = client.create().forPath("/app1","hikktn2".getBytes());
System.out.println(path);
} catch (Exception e) {
e.printStackTrace();
}
}
创建节点类型 --(持久化节点,临时节点,顺序节点)【命令:create -e /节点path】
@Test
public void testCreate3(){
try {
// 设置节点类型 -- CreateMode 枚举类,选择什么关键字就是什么类型节点,持久化节点,临时节点
String path = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app1");
System.out.println(path);
} catch (Exception e) {
e.printStackTrace();
}
}
创建多级节点 -- 可以不再像命令执行一样,先创建父节点,再来创建子节点 【命令:create /父节点path create /子节点path】
@Test
public void testCreate4(){
try {
// 创建多级节点
// 如果父节点不存在,则创建父节点
String path = client.create().creatingParentsIfNeeded().forPath("/app1/h1");
System.out.println(path);
} catch (Exception e) {
e.printStackTrace();
}
}
查询节点 【命令:get /节点path】
@Test
public void testGet1(){
try {
// 查询节点 get
byte[] bytes = client.getData().forPath("/app1");
System.out.println(new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
查询子节点【命令:ls】
@Test
public void testGet2(){
try {
// 查询子节点 ls
List<String> list = client.getChildren().forPath("/app1");
System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
}
}
查询节点状态信息 【命令:ls -s】
@Test
public void testGet3(){
try {
// 查询节点状态信息 ls -s
Stat stat =new Stat();
byte[] bytes = client.getData().storingStatIn(stat).forPath("/app1");
System.out.println(new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
修改节点内容【命令:set /节点path value】
@Test
public void testSet1(){
try {
Stat stat = client.setData().forPath("/app1", "hehe".getBytes());
System.out.println(stat);
} catch (Exception e) {
e.printStackTrace();
}
}
锁定节点后,进行修改节点【命令:stat /节点path [watch] set /节点path value [version]】
@Test
public void testSet2(){
try {
Stat status = new Stat();
//3. 查询节点状态信息:ls -s
client.getData().storingStatIn(status).forPath("/app1");
int version = status.getVersion();//查询出来的 3
System.out.println(version);
client.setData().withVersion(version).forPath("/app1", "hehe".getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
删除节点【命令:delete /节点path】
@Test
public void testDelete() throws Exception {
// 1. 删除单个节点
client.delete().forPath("/app1");
}
删除带有子节点的节点【命令:deleteall /节点path】
@Test
public void testDelete2() throws Exception {
//2. 删除带有子节点的节点
client.delete().deletingChildrenIfNeeded().forPath("/app4");
}
必须成功删除节点
@Test
public void testDelete3() throws Exception {
//3. 必须成功的删除
client.delete().guaranteed().forPath("/app2");
}
删除成功后的回调方法
@Test
public void testDelete4() throws Exception {
//4. 回调
client.delete().guaranteed().inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("我被删除了~");
System.out.println(event);
}
}).forPath("/app1");
}
Zookeeper JavaAPI操作-Watch监听概述
•NodeCache : 只是监听某一个特定的节点
•PathChildrenCache : 监控一个ZNode的子节点.
•TreeCache : 可以监控整个树上的所有节点,类似于PathChildrenCache和NodeCache的组合
监听一个节点注册,当父节点新增父节点的情况,附带一些操作
/**
* 演示 NodeCache:给指定一个节点注册监听器
*/
@Test
public void testNodeCache() throws Exception {
//1. 创建NodeCache对象
final NodeCache nodeCache = new NodeCache(client, "/app1");
//2. 注册监听
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("节点变化了~");
//获取修改节点后的数据
byte[] data = nodeCache.getCurrentData().getData();
System.out.println(new String(data));
}
});
//3. 开启监听.如果设置为true,则开启监听是,加载缓冲数据
nodeCache.start(true);
while (true) {
}
}
监听一个节点注册,监听父节点下的所有子节点变化
@Test
public void testPathChildrenCache() throws Exception {
//1.创建监听对象
PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/app2", true);
//2. 绑定监听器
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("子节点变化了~");
System.out.println(event);
//监听子节点的数据变更,并且拿到变更后的数据
//1.获取类型
PathChildrenCacheEvent.Type type = event.getType();
//2.判断类型是否是update
if (type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)) {
System.out.println("数据变了!!!");
byte[] data = event.getData().getData();
System.out.println(new String(data));
}
}
});
//3. 开启
pathChildrenCache.start();
while (true) {
}
}
监听一个节点注册,包括父节点和父节点下所有子节点变化
/**
* 演示 TreeCache:监听某个节点自己和所有子节点们
*/
@Test
public void testTreeCache() throws Exception {
//1. 创建监听器
TreeCache treeCache = new TreeCache(client, "/app2");
//2. 注册监听
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
System.out.println("节点变化了");
System.out.println(event);
}
});
//3. 开启
treeCache.start();
while (true) {
}
}