目录
Zookeeper的Watch机制
一、概念
类似于数据库中的触发器,对某个Znode设置watcher,当Znode发生变化的时候WatchManager会调用对应的Watcher
当Znode发生删除、修改、创建、子节点修改时的,对应的Watcher会得到通知
二、watcher的特点
1、一次性触发一个Watcher,只会被触发一次,如果需要继续监听,则需要再次添加Watcher
2、事件封装:Watcher得到的时间是被封装过的,包括三个内容keeperState(状态),eventType(类型),path
列表
三、演示watch机制
1、给hello添加一个watch机制,get /hello 后面加上watch表示get的同时添加个watch机制
2、从另一台虚拟机对hello节点进行修改
3、node01这台主机收到了,watch机制的通知
API操作
两种方案:
一、采用Zookeeper原始api,复杂难用
二、采用Zookeeper客户端框架Curator,解决了很多Zookeeper客户端非常底层的细节开发工作
我们用第二种
Curator包含了几个包
Curator-framework:对Zookeeper底层api的封装
Curator0recipes:封装了一些高级特性,例如:Cache时间监听、选举、分布式锁、分布式计数器
maven依赖,使用2.1.2.0的版本对应zook3.4.x,跨版本可能有兼容性问题
一、创建节点
public void createNode() throws Exception{
//1、定义一个重试策略
//这是定义一个连接失败后的策略,第一个参数是重试相隔时间,第二个是最大次数
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1);
//2、获取客户端对象
/*
* p1Zookeeper服务器列表
* p2会话的超时时间
* p3链接超时时间
* p4重试策略
* */
String connectionStr="node01:2181,node02:2181,node03:2181";
CuratorFramework client = CuratorFrameworkFactory.newClient(connectionStr, 8000, 8000, retryPolicy);
//3、开启客户端
client.start();
//4、创建节点
/*
* creatingParentsIfNeeded是允许创建父节点(如果需要)
* withMode创建节点的类型,参数CreateMode是一个枚举
* forPath是路径但是有两个参数,第二个参数是附带的数据,要字节数组
* */
client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/hello2","world".getBytes());
//5、关闭客户端
client.close();
}
注意:用api创建的临时节点是在客户端client.close之后(也就是会话结束),临时节点的生命周期就结束了
二、修改数据
client.setData().forPath();
三、获取节点数据
byte[] bytes = client.getData().forPath("/hello");
System.out.println(new String(bytes));
这里获取到的是一个字节数组要转成string
结果
API操作watch机制
@Test
public void watchNode()throws Exception{
RetryPolicy policy = new ExponentialBackoffRetry(3000, 1);
String connectionStr="node01:2181,node02:2181,node03:2181";
CuratorFramework client = CuratorFrameworkFactory.newClient(connectionStr, 8000, 8000, policy);
client.start();
//一、设置节点的cache,告诉我们要监控哪个节点
//为什么叫treeCache?因为每个节点都可以看做一个树,相当于把树形映射到内存里面形成一个缓冲,是个映射关系
TreeCache treeCache = new TreeCache(client, "/hello2");
//二、设置监听器和处理过程
/*
* getListenable获取监听容器
* addListener添加自定义的监听器
* */
treeCache.getListenable().addListener(new TreeCacheListener() {
/*
* TreeCacheEvent treeCacheEvent这是监听时触发的事件
* */
@Override
public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
//调用getData获取数据
ChildData data = treeCacheEvent.getData();
if (data != null){//如果不为null表被触发了
//三、定义监听类型及触发事件
switch (treeCacheEvent.getType())//判断触发原因
{
case NODE_ADDED:
System.out.println("监控到新增节点");
break;
case NODE_REMOVED:
System.out.println("监控到有节点被移除");
break;
case NODE_UPDATED:
System.out.println("监控到节点被更新");
break;
default:
break;
}
}
}
});
//四、开始监听
treeCache.start();
//延时一段时间用来让我们去触发watch
Thread.sleep(10000000);
//最后关闭客户端
client.close();
}
当对hello2节点进行操作时就会输出
代码格式版
@Test
public void watchNode()throws Exception{
RetryPolicy policy = new ExponentialBackoffRetry(3000, 1);
String connectionStr="node01:2181,node02:2181,node03:2181";
CuratorFramework client = CuratorFrameworkFactory.newClient(connectionStr, 8000, 8000, policy);
client.start();
//一、设置节点的cache,告诉我们要监控哪个节点
//为什么叫treeCache?因为每个节点都可以看做一个树,相当于把树形映射到内存里面形成一个缓冲,是个映射关系
TreeCache treeCache = new TreeCache(client, "/hello2");
//二、设置监听器和处理过程
/*
* getListenable获取监听容器
* addListener添加自定义的监听器
* */
treeCache.getListenable().addListener(new TreeCacheListener() {
/*
* TreeCacheEvent treeCacheEvent这是监听时触发的事件
* */
@Override
public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
//调用getData获取数据
ChildData data = treeCacheEvent.getData();
if (data != null){//如果不为null表被触发了
//三、定义监听类型及触发事件
switch (treeCacheEvent.getType())//判断触发原因
{
case NODE_ADDED:
System.out.println("监控到新增节点");
break;
case NODE_REMOVED:
System.out.println("监控到有节点被移除");
break;
case NODE_UPDATED:
System.out.println("监控到节点被更新");
break;
default:
break;
}
}
}
});
//四、开始监听
treeCache.start();
//延时一段时间用来让我们去触发watch
Thread.sleep(10000000);
//最后关闭客户端
client.close();
}
当对hello2节点进行操作时就会输出