ZooKeeper Watch Java API浅析exists
2023-09-27 14:29:33 时间
Watch是ZooKeeper中非常重要的一个机制,它可以监控ZooKeeper中节点的变化情况,告知客户端。下面,我们以代码为例来分析Watch在ZooKeeper中是如何实现的。ZooKeeper中一共由三种方法可以实现Watch,分别为getData、exists和getChildren,今天我们先来看下exists()方法:
2、exists()
import java.io.IOException; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.data.Stat; public class TestZooKeeperWatcher { public static void main(String[] args) { ZooKeeper zk = null; try { System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("开始连接ZooKeeper..."); // 创建与ZooKeeper服务器的连接zk String address = "192.168.1.226:2181"; int sessionTimeout = 3000; zk = new ZooKeeper(address, sessionTimeout, new Watcher() { // 监控所有被触发的事件 public void process(WatchedEvent event) { if (event.getType() == null || "".equals(event.getType())) { return; System.out.println("已经触发了" + event.getType() + "事件!"); System.out.println("ZooKeeper连接创建成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 创建根目录节点 // 路径为/tmp_root_path // 节点内容为字符串"我是根目录/tmp_root_path" // 创建模式为CreateMode.PERSISTENT System.out.println("开始创建根目录节点/tmp_root_path..."); zk.create("/tmp_root_path", "我是根目录/tmp_root_path".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("根目录节点/tmp_root_path创建成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 创建第一个子目录节点 // 路径为/tmp_root_path/childPath1 // 节点内容为字符串"我是第一个子目录/tmp_root_path/childPath1" // 创建模式为CreateMode.PERSISTENT System.out.println("开始创建第一个子目录节点/tmp_root_path/childPath1..."); zk.create("/tmp_root_path/childPath1", "我是第一个子目录/tmp_root_path/childPath1".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("第一个子目录节点/tmp_root_path/childPath1创建成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 创建第二个子目录节点 // 路径为/tmp_root_path/childPath2 // 节点内容为字符串"我是第二个子目录/tmp_root_path/childPath2" // 创建模式为CreateMode.PERSISTENT System.out.println("开始创建第二个子目录节点/tmp_root_path/childPath2..."); zk.create("/tmp_root_path/childPath2", "我是第二个子目录/tmp_root_path/childPath2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("第二个子目录节点/tmp_root_path/childPath2创建成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 修改第一个子目录节点/tmp_root_path/childPath1数据 System.out.println("开始修改第一个子目录节点/tmp_root_path/childPath1数据..."); zk.setData("/tmp_root_path/childPath1", "我是修改数据后的第一个子目录/tmp_root_path/childPath1".getBytes(), -1); System.out.println("修改第一个子目录节点/tmp_root_path/childPath1数据成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 修改第二个子目录节点/tmp_root_path/childPath2数据 System.out.println("开始修改第二个子目录节点/tmp_root_path/childPath2数据..."); zk.setData("/tmp_root_path/childPath2", "我是修改数据后的第二个子目录/tmp_root_path/childPath2".getBytes(), -1); System.out.println("修改第二个子目录节点/tmp_root_path/childPath2数据成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 获取根目录节点状态 System.out.println("开始获取根目录节点状态..."); System.out.println(zk.exists("/tmp_root_path", true)); System.out.println("根目录节点状态获取成功"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 删除第一个子目录节点 System.out.println("开始删除第一个子目录节点/tmp_root_path/childPath1..."); zk.delete("/tmp_root_path/childPath1", -1); System.out.println("第一个子目录节点/tmp_root_path/childPath1删除成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 删除第二个子目录节点 System.out.println("开始删除第二个子目录节点/tmp_root_path/childPath2..."); zk.delete("/tmp_root_path/childPath2", -1); System.out.println("第二个子目录节点/tmp_root_path/childPath2删除成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); // 删除根目录节点 System.out.println("开始删除根目录节点/tmp_root_path..."); zk.delete("/tmp_root_path", -1); System.out.println("根目录节点/tmp_root_path删除成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("..."); } catch (IOException | KeeperException | InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { // 关闭连接 if (zk != null) { try { zk.close(); System.out.println("释放ZooKeeper连接成功!"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }执行结果如下:
... 开始连接ZooKeeper... ZooKeeper连接创建成功! 已经触发了None事件! 开始创建根目录节点/tmp_root_path... 根目录节点/tmp_root_path创建成功! 开始创建第一个子目录节点/tmp_root_path/childPath1... 第一个子目录节点/tmp_root_path/childPath1创建成功! 开始创建第二个子目录节点/tmp_root_path/childPath2... 第二个子目录节点/tmp_root_path/childPath2创建成功! 开始修改第一个子目录节点/tmp_root_path/childPath1数据... 修改第一个子目录节点/tmp_root_path/childPath1数据成功! 开始修改第二个子目录节点/tmp_root_path/childPath2数据... 修改第二个子目录节点/tmp_root_path/childPath2数据成功! 开始获取根目录节点状态... 2007741,2007741,1458963342014,1458963342014,0,2,0,0,29,2,2007743 根目录节点状态获取成功 开始删除第一个子目录节点/tmp_root_path/childPath1... 第一个子目录节点/tmp_root_path/childPath1删除成功! 开始删除第二个子目录节点/tmp_root_path/childPath2... 第二个子目录节点/tmp_root_path/childPath2删除成功! 开始删除根目录节点/tmp_root_path... 已经触发了NodeDeleted事件! 根目录节点/tmp_root_path删除成功! 释放ZooKeeper连接成功!而如果我们在获取根目录节点状态之后,修改根目录数据,添加代码和执行结果如下:
// 修改根目录节点数据 System.out.println("开始修改根目录节点/tmp_root_path数据..."); zk.setData("/tmp_root_path", "我是修改数据后的根目录/tmp_root_path".getBytes(), -1); System.out.println("修改根目录节点/tmp_root_path数据成功!"); Thread.currentThread().sleep(1000l); System.out.println("..."); System.out.println("..."); System.out.println("..."); System.out.println("...");
... 开始连接ZooKeeper... ZooKeeper连接创建成功! 已经触发了None事件! 开始创建根目录节点/tmp_root_path... 根目录节点/tmp_root_path创建成功! 开始创建第一个子目录节点/tmp_root_path/childPath1... 第一个子目录节点/tmp_root_path/childPath1创建成功! 开始创建第二个子目录节点/tmp_root_path/childPath2... 第二个子目录节点/tmp_root_path/childPath2创建成功! 开始修改第一个子目录节点/tmp_root_path/childPath1数据... 修改第一个子目录节点/tmp_root_path/childPath1数据成功! 开始修改第二个子目录节点/tmp_root_path/childPath2数据... 修改第二个子目录节点/tmp_root_path/childPath2数据成功! 开始获取根目录节点状态... 2007775,2007775,1458963528012,1458963528012,0,2,0,0,29,2,2007777 根目录节点状态获取成功 开始修改根目录节点/tmp_root_path数据... 已经触发了NodeDataChanged事件! 修改根目录节点/tmp_root_path数据成功! 开始删除第一个子目录节点/tmp_root_path/childPath1... 第一个子目录节点/tmp_root_path/childPath1删除成功! 开始删除第二个子目录节点/tmp_root_path/childPath2... 第二个子目录节点/tmp_root_path/childPath2删除成功! 开始删除根目录节点/tmp_root_path... 根目录节点/tmp_root_path删除成功! 释放ZooKeeper连接成功!与getData()一致!
结论:
exists()方法仅仅监控对应节点的一次数据变化,无论是数据修改还是删除!若要每次对应节点发生变化都被监测到,那么每次都得先调用exists()方法获取一遍节点状态!
Java--安装和用原生API连接Zookeeper Zookeeper是一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
【ZooKeeper】③ Java 代码使用 ZooKeeper ZooKeeper 中的 get 命令可查看节点中存储的数据,并绑定【节点数据改变事件】(是一次性事件) ZooKeeper 中的 list 命令可查看子节点列表,并绑定【节点改变事件】(是一次性事件)
相关文章
- Java架构师-分布式(六):分布式锁【基于Redis的分布式锁(Api:Redisson)、基于zookeeper的分布式锁(Api:Curator)】
- java之搭建webservice服务端
- java之多态(一)
- 算法java实现--动态规划--电路布线问题
- 第一章 Java加解密简介
- Java多线程之 Thread VS Runnable 【带案例】
- Java Calendar 类的时间操作
- Java EE之Hibernate异常总结org.hibernate.MappingException: Repeated column in mapping for entity:
- 在Java中如何高效的判断数组中是否包含某个元素
- zookeeper java调用及权限控制
- Java 25天基础-DAY 05-面向对象-构造函数
- 1016 部分A+B(JAVA)
- java 分隔函数split("",-1)的用途
- java,javascript对18位身份证格式的验证算法
- 大数据ZooKeeper(五):ZooKeeper Java API操作