1.安装
...................
2.Zookeeper常见命令
①create命令创建节点
create [-s][ -e] path data acl
-s:顺序节点 -e:临时节点 都不加为持久节点 path:节点名称 data节点值 acl权限
②读取节点
ls path
path:表示
命令名称 | 命令 | 命令说明 |
create(创建节点) | create [-s][ -e] path data acl | -s:顺序节点 -e:临时节点 都不加为持久节点 path:节点名称 data节点值 acl权限 |
ls(获取节点信息) | ls path | path:节点路径 |
get(获取节点数据和属性) | get path | path:节点路径 |
set(更新节点) | set path data [version] | version:数据版本号 Zookeeper节点中数据是有版本的概念的(指定版本进行更新的 锁的概念) |
delete(删除) | delete path [version] | version:同上 注:如果一个节点有子节点,不能直接删除这个节点,需要先删除这个子节点 |
3.java客户单API使用
创建Zookeeper实例来连接Zookeeper服务器
{
try {
//await() 阻塞当前进程 当countDown()减1 当count数量为0的时候阻塞才会结束
CountDownLatch latch = new CountDownLatch(1);
//connectString:连接字符串 timeout:会话的超时时间,watcher:事件监听机制 canBeReadOnly:只读模式
//事件监听 zookeeper连接时异步连接,Watcher事件监听 是回调函数 默认的监听
/*
new Watcher() {
//事件监听 zookeeper连接时异步连接,Watcher事件监听 是回调函数
@Override
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState() == Event.KeeperState.SyncConnected){
latch.countDown();
}
}
}
*/
ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 1000, watchedEvent -> {
if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected){
latch.countDown();
}
});
latch.await();
//创建节点 path:节点路径 data 节点值(序列化)acl权限 createMode 节点性质EPHEMERAL(临时)PERSISTENT持久节点
//EPHEMERAL_SEQUENTIAL(临时顺序) PERSISTENT_SEQUENTIAL(持久顺序)
//临时节点
zk.create("/hqz","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
/*
@Override
public void processResult(int i, String s, Object o, String s1) {
}
*/
//i result code响应码 0成功 -4客户端服务端断开连接 -110节点不存在 -112会话过期
// s路径 o
// ctx上下文
// s1节点名称
//持久节点
//异步 回调函数
zk.create("/hz","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT, (i, s, o, s1) -> {
System.out.println("i:" + i + " s:" + s + " o:" + o + " s1:" + s1);
},"11");
//同步获取数据
Stat stat = new Stat();
byte[] bytes = zk.getData("/hqz",true,stat);
System.out.println(new String(bytes));
//删除先删除子节点
//同步删除
zk.delete("/hz",stat.getVersion());
//异步删除
//VoidCallBack()
zk.delete("/hz", stat.getVersion(), (i, s, o) -> {
System.out.println("i:" + i + " s:" + s + " o:" + o);
},"22");
//创建节点只能一级一级的创建
//zk.create("/qz","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//zk.create("/qz/hqz","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//zk.create("/qz/hz","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//path:节点路径 watch:子节点监听
List<String> nodes = zk.getChildren("/qz",true);
nodes.forEach(str-> System.out.println(str));
/**
* 注在Zookeeper原生的API中watch监听不能提供反复监听功能
*/
zk.getChildren("/qz", watchedEvent -> {
try {
List<String> node = zk.getChildren(watchedEvent.getPath(),true);
node.forEach(str-> System.out.println("change" + str));
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// zk.create("/qz/hzq2","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//更新节点数据 同步 watch true 数据改变走默认的watch监听
byte[] b = zk.getData("/qz",true,stat);
System.out.println("qz1:" + new String(b));
zk.setData("/qz","2".getBytes(),stat.getVersion());
b = zk.getData("/qz",true,stat);
System.out.println("qz1:" + new String(b));
//异步更新
//new AsyncCallback.StatCallback() {
// @Override
// public void processResult(int i, String s, Object o, Stat stat) {
// }
//}
zk.setData("/qz", "3".getBytes(), stat.getVersion(), (i, s, o, stat1) -> {
System.out.println("qz:" + "i:" + i + " s" + " o:" + o + " stat1:" + stat1.getVersion());
try {
System.out.println("qz:" + new String (zk.getData("/qz",true,stat)));
System.out.println(stat.getVersion());
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"333");
//检测节点是否存在 同步
Stat stat1 = zk.exists("/first", watchedEvent -> {
System.out.println("节点路径0:" + watchedEvent.getPath());
});
zk.delete("/first",stat1.getVersion());
//异步检测节点是否存在
zk.exists("/first", watchedEvent -> {
System.out.println("节点路径1:" + watchedEvent.getPath());
}, (i, s, o, stat2) -> {
System.out.println("first:" +"i:" + i + " s:" + s + "o:" + o + "stat2:" + stat2.getVersion());
},"double");
//zk.delete("/double1",stat1.getVersion());
zk.create("/first","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.getData("/first", false, stat);
System.out.println("stat:" + stat.getVersion());
Thread.sleep(10000);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e){
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
}
}
4.zkClient 封装了原生的API,提供了Session超时重连、watch反复注册等功能。
public static void main(String[] args) throws InterruptedException {
//穿件连接
//在zkClient中奖ZK连接异步化转换为同步化 connectionTimeout连接超时 SessionTimeOut session超时 默认30000毫秒
ZkClient zkClient = new ZkClient("127.0.0.1:2181",5000,3000);
//创建节点 返回节点信息
// String str = zkClient.create("/zkClientQQ","zkClientQQ", CreateMode.PERSISTENT);
//System.out.println(str);///zkClient
//createParents 是否创建父节点 原生API中创建子节点需要先创建父节点才能创建子节点
//创建的节点内容为null
//zkClient.createPersistent("/zkClient1/zkClient2",true);
//删除节点
//zkClient.delete("/zkClient");
//删除节点 以及该节点的子节点 原生API删除节点之前必须要先删除其子节点
//zkClient.deleteRecursive("/zkClient1");
//List<String> client = zkClient.getChildren("/");
//client.forEach(s-> System.out.println("client:" + s));
//获取子节点列表
//List<String> client1 = zkClient.getChildren("/zkClient1");
//client1.forEach(s-> System.out.println("client1:" + s));
/**
* s:父节点 list子节点路径列表
* @Override
* public void handleChildChange(String s, List<String> list) throws Exception {
* }
* 监听:新增子节点、更新子节点、删除子节点
* 若删除主节点:s为主节点的全路径 list为null
* 可以监听不存在的节点当节点创建的时候list为[]
*
*/
/*zkClient.subscribeChildChanges("/zkClient-1", (s, list) -> {
System.out.println("s:" + s);
System.out.println("list:" + list);
});
String data = zkClient.readData("/zkClient");
System.out.println("data:" + data);
Stat stat = new Stat();
String data1 = zkClient.readData("/zkClient",stat);
System.out.println("data1:" + data1);
System.out.println("stat:" + stat.getVersion());
String data3 = zkClient.readData("/zkClientqq",true);
System.out.println("data3:" + data3);*/
/**
* Exception in thread "main" org.I0Itec.zkclient.exception.ZkMarshallingError: java.io.EOFException
* at org.I0Itec.zkclient.serialize.SerializableSerializer.deserialize(SerializableSerializer.java:37)
* 序列化的问题 没有反序列化
* zkClient添加节点和获取节点数据 会序列化和反反序列化
*
*
*/
//设置反序列化器
zkClient.setZkSerializer(new MyZkSerializer());
//zxClient 默认的反序列化器
//zkClient.setZkSerializer(new SerializableSerializer());
String b =zkClient.readData("/zkClientQQ");
System.out.println("b:" + b);
/**
* 监听数据改变
*/
zkClient.subscribeDataChanges("/zkClientQQ", new IZkDataListener() {
/**
* s 路径 o 节点内容
* @param s
* @param o
* @throws Exception
*/
@Override
public void handleDataChange(String s, Object o) throws Exception {
System.out.println("Change s:" + s);
System.out.println("Object o:" + o);
}
/**
* s 路径
* @param s
* @throws Exception
*/
@Override
public void handleDataDeleted(String s) throws Exception {
System.out.println("delete s:" + s);
}
});
//写数据
//zkClient.writeData("/zkClientQQ","9999");
//expectedVersion版本号
//zkClient.writeData("/zkClientQQ","8888",1);
//判断节点是否存在
boolean flag = zkClient.exists("/zkClientQQ");
System.out.println(flag);
Thread.sleep(1000000);
}
5.curator的简单使用
public static void main(String[] args) throws Exception {
/**
* [ˌekspəˈnenʃl]指数 倡导者 例子
* 默认的重连策略 ExponentialBackoffRetry 参数说明
* baseSleepTimeMs初始sleep时间
* maxRetries 最大重试次数
* maxSleepMs 最大sleep时间
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
/**
* sleepMsBetweenRetry sleep时间
* n重连次数
* new RetryNTimes(n,sleepMsBetweenRetry);
* new RetryOneTime(sleepMsBetweenRetry);
*
*/
/**
* 默认的重连策略有4中
* ExponentialBackoffRetry
* RetryNTimes
* RetryOneTime
* RetryUntilElapsed
*
*
* 定义自定义的重试策略
* @Override
* public boolean allowRetry(int i, long l, RetrySleeper retrySleeper) {
* return false;
* }
*/
//创建会话
//CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", 5000, 3000, retryPolicy);
//启动
//client.start();
//使用fluent模式创建会话
CuratorFramework client = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181")
.sessionTimeoutMs(5000).retryPolicy(retryPolicy).namespace("base").build();
client.start();
//创建节点 值为空 节点类型为持久化
client.create().forPath("/h1");
//创建带值的节点
client.create().forPath("/h1","123".getBytes());
//withMode 指定节点类型
client.create().withMode(CreateMode.PERSISTENT).forPath("/h3","h3".getBytes());
//creatingParentContainersIfNeeded 创建父节点 临时节点 注:只有叶子节点为临时节点 非叶子节点为持久节点(Zookeeper特性)
client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/h4/h44","h4".getBytes());
//只能删除叶子节点
//client.delete().forPath("/h1");
//删除一个节点并递归删除子节点
//client.delete().deletingChildrenIfNeeded().forPath("/h4");
//强制删除一个节点 只要客户端会话有效 会在后台进行持续删除,直到节点删除成功
//client.delete().guaranteed().forPath("/h4");
//读取节点的数据
client.getData().forPath("/h1");
//读取节点并返回 stat
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("/h1");
client.setData().forPath("/h1","h11".getBytes());
//更新指定版本的数据
client.setData().withVersion(1).forPath("/h1","h111".getBytes());
CountDownLatch countDownLatch = new CountDownLatch(1);
/**
* inBackground(BackgroundCallback,Executor)
* 在Zookeeper中所有异步事件都是由 EventThread 这个线程 EventThread的串行处理机制在绝大多数情况下能保证事件处理的顺序性
* 弊端:一但处理复杂的业务,消耗较长的时间会影响,其它时间的执行
* curator中可以允许用户传一个线程池Executor,这样就可以把复杂的时间放到一个专门的线程中去处理
*/
//异步创建
client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
/**
*
* @param curatorFramework 客户端实例 例如 响应码:0成功 -4 连接丢失 -110节点存在 -112 session超时
* @param curatorEvent 服务端类型 getType() 代表本次事件 create delete get_data set_data ....
* @throws Exception
*/
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
System.out.println("");
countDownLatch.countDown();
}
}).forPath("/hh","hh".getBytes());
countDownLatch.await();
监听
/**
*
* dataIsCompressed 是否进行数据压缩 true 会在NodeCache第一启动的时候从Zookeeper上取出数据存到缓存中去
*
*/
NodeCache nodeCache = new NodeCache(client,"/h1",false);
nodeCache.start();
nodeCache.getListenable().addListener(new NodeCacheListener() {
/**
* 监听节点内容改变 以及节点创建 但是节点删除不会触发
* @throws Exception
*/
@Override
public void nodeChanged() throws Exception {
//获取数据值
System.out.println(new String(nodeCache.getCurrentData().getData()));
}
});
ExecutorService executor = Executors.newFixedThreadPool(3);
/**
* cacheData:是否把节点内容缓存起来,true时当节点列表变更时,会将节点内容缓存起来
* dataIsCompressed:
* executorService:专门用一个线程池来处理事件通知
*
*/
PathChildrenCache pathChildrenCache =new PathChildrenCache(client,"/h4",true,true,executor);
pathChildrenCache.start();
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
/**
*注:无法对二级子节点进行监听(Zookeeper也是) 例如:能监听/h4/h4 不能监听 /h4/h4/h4
* @param curatorFramework 客户端
* @param pathChildrenCacheEvent 事件类型 定义了子节点的事件类型 child_added child_updated child_removed
* @throws Exception
*/
@Override
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
switch (pathChildrenCacheEvent.getType()){
case CHILD_ADDED:
System.out.println("CHILD_ADDED :" + pathChildrenCacheEvent.getData());
break;
case CHILD_REMOVED:
System.out.println("CHILD_REMOVED :" + pathChildrenCacheEvent.getData());
break;
case CHILD_UPDATED:
System.out.println("CHILD_UPDATED :" + pathChildrenCacheEvent.getData());
break;
}
}
});
}