一 zk 实现分布式锁
1.1 zk分布式操作命令
1.1.1 常用命令说明
1.查看某个节点下的子节点: ls /
2.查看某个节点的内容: get /zookeeper
3.创建持久化节点: create /aa "test"
4.删除节点: delete /aa
5.查看节点状态:stat /
6. 设置节点的内容 set /aa "test1"
1.1.2 znode节点类型
永久节点:create /path content
临时节点:create -e /path content 。只要客户端程序断开链接自动删除
永久序列化节点:create -s /path content
临时序列化节点:create -s -e /path content
1.1.3 znode节点独占排它特性
相同节点具有唯一性,只允许创建一次,具有独占排它的特性。
1.2 zk的4种目录树
zookeeper提供一个多层级的节点命名空间(节点称为znode),每个节点都用一个以斜杠(/)分隔的路径表示,而且每个节点都有父节点(根节点除外),非常类似于文件系统。并且每个节点都是唯一的。znode节点有四种类型:
1.PERSISTENT:永久节点。客户端与zookeeper断开连接后,该节点依旧存在
2.EPHEMERAL:临时节点。客户端与zookeeper断开连接后,该节点被删除
3.PERSISTENT_SEQUENTIAL:永久节点、序列化。客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
4.EPHEMERAL_SEQUENTIAL:临时节点、序列化。客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
1.3 实战操作
1.进入zk客户端
./zkCli.sh # 查看zk客户端
2.创建节点命令
[zk: localhost:2181(CONNECTED) 12] get /sz
test
[zk: localhost:2181(CONNECTED) 13] set /sz test123
[zk: localhost:2181(CONNECTED) 14] get /sz
test123
[zk: localhost:2181(CONNECTED) 15]
3.案例
[zk: localhost:2181(CONNECTED) 0] create /aa test # 创建持久化节点
Created /aa
[zk: localhost:2181(CONNECTED) 1] create -s /bb test # 创建持久序列化节点
Created /bb0000000001
[zk: localhost:2181(CONNECTED) 2] create -e /cc test # 创建临时节点
Created /cc
[zk: localhost:2181(CONNECTED) 3] create -e -s /dd test # 创建临时序列化节点
Created /dd0000000003
[zk: localhost:2181(CONNECTED) 4] ls / # 查看某个节点下的子节点
[aa, bb0000000001, cc, dd0000000003, zookeeper]
[zk: localhost:2181(CONNECTED) 5] stat / # 查看某个节点的状态
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x5
cversion = 3
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 5
[zk: localhost:2181(CONNECTED) 6] get /aa # 查看某个节点的内容
test
[zk: localhost:2181(CONNECTED) 11] delete /aa # 删除某个节点
[zk: localhost:2181(CONNECTED) 7] ls / # 再次查看
[bb0000000001, cc, dd0000000003, zookeeper]
1.4 zk的监听事件
1.4.1 说明
在读取数据时,我们可以同时对节点设置事件监听,当节点数据或结构变化时,zookeeper会通知客户端。当前zookeeper针对节点的监听有如下四种事件:
1.监听节点创建 :使用监听命令: stat -w /xx
2.监听节点删除: 使用监听命令: stat -w /xx
3.监听节点数据变化: 使用监听命令 : get -w /xx
4.监听子节点变化: 使用监听命令 ls -w /xxx
1.4.2 案例,监听节点创建
1.客户端1
2.客户端2
1.4.3 案例,监听节点删除
1.客户端1
2.客户端2: stat -w /bb
1.4.4 案例,监听数据变化
1.客户端1
[zk: localhost:2181(CONNECTED) 28] set /teng 1234
[zk: localhost:2181(CONNECTED) 29]
2.客户端2:会提示目录/teng 发生了改变
1.客户端1
2.客户端2
1.4.5 案例,子节点变化
1.客户端1
2.客户端2: 子节点发生变化
1.5 zk的Java Api的操作
1.java代码
package com.atguigu.distributed.lock.util;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* @ClassName: TestZk
* @Description: TODO
* @Author: admin
* @Date: 2023/12/29 11:21:01
* @Version: V1.0
**/
public class TestZk {
public static void main(String[] args) throws KeeperException, InterruptedException {
// 获取zookeeper链接
CountDownLatch countDownLatch = new CountDownLatch(1);
ZooKeeper zooKeeper = null;
try {
zooKeeper = new ZooKeeper("192.168.43.4:2181", 30000, new Watcher() {
@Override
public void process(WatchedEvent event) {
if (Event.KeeperState.SyncConnected.equals(event.getState())
&& Event.EventType.None.equals(event.getType())) {
System.out.println("获取链接成功。。。。。。" + event);
countDownLatch.countDown();
}
else if(Event.KeeperState.Closed.equals(event.getState())){
System.out.println("==================关闭链接成功!!");
}
}
});
countDownLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
//创建节点
createInfo(zooKeeper);
//判断节点是否存在
Stat stat = existInfo(zooKeeper);
//监听节点
listenerInfo(zooKeeper);
//获取节点内容
getNodenfo(zooKeeper);
//查询子节点
getChildrenInfo(zooKeeper);
//更新节点内容
updateNodeContent(zooKeeper);
// 删除一个节点
System.out.println("version:"+stat.getVersion());
//-1表示不关心版本号
zooKeeper.delete("/pabank/aa", -1);
// if (zooKeeper != null){
// System.out.println("关闭...");
// zooKeeper.close();
// }
System.out.println("over......");
}
/**
* @author admin
* @description 创建节点
* @date 2023/12/29 11:25
* @param [zooKeeper]
* @return void
*/
public static void createInfo( ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
// 创建一个节点,1-节点路径 2-节点内容 3-节点的访问权限 4-节点类型
// OPEN_ACL_UNSAFE:任何人可以操作该节点
//CREATOR_ALL_ACL:创建者拥有所有访问权限
//READ_ACL_UNSAFE: 任何人都可以读取该节点
//1.创建一个,任何人都可以操作的永久节点
System.out.println("eee");
// zooKeeper.create("/pabank", "aa".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// zooKeeper.create("/pabank/aa", "aa".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//2.创建一个,任何人都可以操作的临时节点
// zooKeeper.create("/pabank/bb", "bb~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
// //3.创建一个,任何人都可以操作的永久顺序节点
zooKeeper.create("/pabank/cc", "cc~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
// //4.创建一个,任何人都可以操作的临时顺序节点
// zooKeeper.create("/pabank/dd", "dd~~".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// //6.创建一个创建者拥有所有访问权限,可以操作的临时顺序节点
// zooKeeper.create("/atguigu/dd", "haha~~".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("创建成功...");
}
/**
* @author admin
* @description 创建节点是否存在
* @date 2023/12/29 11:57
* @param [zooKeeper]
* @return void
*/
public static Stat existInfo(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
// 判断节点是否存在
Stat stat = zooKeeper.exists("/pabank", true);
if (stat != null){
System.out.println("当前节点存在!" + stat.getVersion());
} else {
System.out.println("当前节点不存在!");
}
return stat;
}
public static void listenerInfo(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
// 判断节点是否存在,同时添加监听
zooKeeper.exists("/pabank", event -> {
System.out.println("监听event:"+event);
});
}
/**
* @author admin
* @description 获取节点的数据
* @date 2023/12/29 16:44
* @param [zooKeeper]
* @return void
*/
public static void getNodenfo(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
// 获取一个节点的数据
byte[] data = zooKeeper.getData("/pabank/aa", false, null);
System.out.println("节点内容"+new String(data));
}
/**
* @author admin
* @description 查询一个节点的所有子节点
* @date 2024/1/2 17:28
* @param [zooKeeper]
* @return void
*/
public static void getChildrenInfo(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
// 查询一个节点的所有子节点
List<String> children = zooKeeper.getChildren("/pabank", false);
System.out.println("子节点内容children:"+children);
}
/**
* @author admin
* @description 更新节点内容
* @date 2024/1/2 17:29
* @param []
* @return void
*/
public static void updateNodeContent(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
// 更新
Stat stat=existInfo(zooKeeper);
zooKeeper.setData("/pabank", "wawa...".getBytes(), stat.getVersion());
System.out.println("修改内容:"+"wawa");
}
}
2.执行结果
3.删除节点: 子节点pabank/aa 中 /aa进行了删除