zookeeper节点操作
- zookeeper节点操作
- 节点创建,删除,遍历
- 节点数据读写
- 节点类型
节点类型
持久节点 PERSISTENT
持久顺序节点 PERSISTENT_SEQUENTIAL
临时节点 EPHEMERAL
临时顺序节点 EPHEMERAL_SEQUENTIAL
节点操作见实例代码
public class ConnectionWatcher implements Watcher {
private static final int SESSION_TIMEOUT = 5000;
public ZooKeeper zk;
private CountDownLatch connectedSignal = new CountDownLatch(1);
public void connect(String host) throws IOException {
try {
zk=new ZooKeeper(host,SESSION_TIMEOUT,this);
connectedSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void closeZk() throws InterruptedException {
zk.close();
}
@Override
public void process(WatchedEvent watchedEvent) {
if(watchedEvent.getState()==Watcher.Event.KeeperState.SyncConnected)
connectedSignal.countDown();
System.out.println("监听到事件!");
}
}
public class ZookeeperTest extends ConnectionWatcher{
@Override
public void connect(String host) throws IOException {
super.connect(host);
}
@Override
public void closeZk() throws InterruptedException{
super.closeZk();
}
@Override
public void process(WatchedEvent watchedEvent) {
super.process(watchedEvent);
System.out.println("数据已修改");
}
public static void main(String[] args) throws Exception{
ZookeeperTest zookeeperTest = new ZookeeperTest();
zookeeperTest.connect("192.168.31.201:2181");
String fatherNode="testZookeeper";
// zookeeperTest.createZNode("testZookeeper");
// zookeeperTest.join(fatherNode, "twoPath");
// Thread.sleep(30000);
// zookeeperTest.listGroup(fatherNode);
String data="this is zookeeper data";
zookeeperTest.wrideDataToNode(fatherNode,data,-1);
zookeeperTest.getDataFromNode(fatherNode);
// zookeeperTest.deleteNode(fatherNode);
Thread.currentThread().suspend();
}
/**
* 在给定的节点下创建临时节点
* @param groupName
* @param numberName
* @throws Exception
*/
public void join(String groupName,String numberName)throws Exception{
String path="/"+groupName+"/"+numberName;
String createPath=zk.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println(createPath);
}
/**
* 获取 指定节点下的子节点
* @param groupName
* @throws KeeperException
* @throws InterruptedException
*/
public void listGroup(String groupName) throws KeeperException, InterruptedException {
String patchGroup="/"+groupName;
List<String>listNode=zk.getChildren(patchGroup,false);
if(listNode.isEmpty()){
System.out.print("this is no child Node");
}else{
System.out.print(listNode.toString());
}
}
/**
* 删除指定 节点 以及子节点
* 不支持递归删除,只能从子节点往上删除
* @param groupName
* @throws KeeperException
* @throws InterruptedException
*/
public void deleteNode(String groupName) throws KeeperException, InterruptedException {
String patchGroup="/"+groupName;
List<String> childrenNodes=zk.getChildren(patchGroup,false);
for(String node:childrenNodes){
zk.delete(patchGroup+"/"+node,-1 );
}
zk.delete(patchGroup,-1);
System.out.println("delete OK");
}
/**
* 创建指定永久节点
* @param zNode
* @throws Exception
*/
public void createZNode(String zNode) throws Exception{
String path="/"+zNode;
String createPath = zk.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(createPath);
}
/**
* version -1 基于数据最新版本进行更新操作
* @param zNode
* @param data
* @param version
*/
public void wrideDataToNode(String zNode,String data,int version){
String path="/"+zNode;
try {
zk.setData(path,data.getBytes(),version);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("向节点"+path+"写入成功!");
}
public void getDataFromNode(String zNode){
String path="/"+zNode;
try {
System.out.println( new String(zk.getData(path,true,null)));
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Curator zookeeper 实现分布式锁
- 原理
- 临时顺序节点
- 实例代码
- 关于版本问题
Curator zookeeper 实现分布式锁
原理
每个JVM使用同一个客户端实例,客户端实例对某个方法加锁的时候,
zookeeper对应节点下生成一个唯一的临时顺序节点,如果是序号最小的,则获得锁,释放锁的时候删除节点。
怠机的时候临时节点会自动删除,不会有死锁。
临时顺序节点
如图是调试过程中 在zookeeper中生成用于判断锁的临时顺序节点
实例代码
private static final String ZK_ADDRESS = "192.168.31.201:2181";//地址
private static final String ZK_LOCK_PATH = "/zktest";//path
static SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws Exception {
// CuratorFramework client= CuratorFrameworkFactory.newClient(ZK_ADDRESS,new RetryNTimes(10,5000));
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client= CuratorFrameworkFactory.newClient(ZK_ADDRESS,3000, 1000, retryPolicy);
client.start();
InterProcessMutex lock =new InterProcessMutex(client,ZK_LOCK_PATH);
Thread thread1 =new Thread(()->{
doWithLock(client,lock);
},"t1");
Thread thread2 =new Thread(()->{
doWithLock(client,lock);
},"t2");
Thread thread3 =new Thread(()->{
doWithLock(client,lock);
},"t3");
thread1.start();
thread2.start();
thread3.start();
}
private static void doWithLock(CuratorFramework client, InterProcessMutex lock) {
Boolean isLock=false;
System.out.println("进入线程"+Thread.currentThread().getName()+":"+time.format(new Date()));
try {
if(lock.acquire(1, TimeUnit.SECONDS)){//1秒的时间等待锁
isLock=true;
System.out.println(Thread.currentThread().getName()+"获取锁成功!执行加锁任务"+time.format(new Date()));
Thread.sleep(2000L);
}else{
System.out.println("获取锁超时!");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println(Thread.currentThread().getName()+"释放锁!"+time.format(new Date()));
try {
if(isLock){
lock.release();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
pom.xml
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-client -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>2.12.0</version>
</dependency>
关于版本问题
Curator 2.x.x兼容Zookeeper的3.4.x和3.5.x。
而Curator 3.x.x只兼容Zookeeper 3.5.x,并且提供了一些诸如动态重新配置、watch删除等新特性。