0. 前言
1. 开发环境配置
1.1 idea创建一个maven工程
1.2 pom配置jar
4.0.0
com.rocky.learn
zk
1.0-SNAPSHOT
UTF-8
junit
junit
3.8.1
test
org.apache.zookeeper
zookeeper
3.4.6
log4j
log4j
1.2.16
org.slf4j
slf4j-api
1.6.1
View Code
2. API使用
2.1 连接Zookeep Server
code
importorg.apache.zookeeper.WatchedEvent;importorg.apache.zookeeper.Watcher;importorg.apache.zookeeper.ZooKeeper;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/12.*/
public class ZookeeperTestConnection implementsWatcher {private static CountDownLatch countDownLatch = new CountDownLatch(1);public voidprocess(WatchedEvent event) {
System.out.println("receive the event:"+event);if(Event.KeeperState.SyncConnected ==event.getState())
countDownLatch.countDown();
}public static final String ADDRESS = "192.168.1.8:2181";public static void main(String[] args) throwsIOException {
ZooKeeper zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestConnection());
System.out.println(zooKeeper.getState());try{
countDownLatch.await();
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("zookeeper session established");
}
}
View Code
控制台
2.2 创建节点
2.2.1 同步创建
code
import org.apache.zookeeper.*;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/12.*/
public class ZookeeperTestCreateNodeSync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "192.168.1.8:2181";private static final String PREFIX = "/mytest-sync-create-";public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestCreateNodeSync());
System.out.println("state:"+zooKeeper.getState());
countDownLatch.await();
String path1= zooKeeper.create(PREFIX, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("success create znode:"+path1);
String path2= zooKeeper.create(PREFIX, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("success create znode:"+path2);
zooKeeper.close();
}public voidprocess(WatchedEvent event) {//连上了
if(Event.KeeperState.SyncConnected ==event.getState())
countDownLatch.countDown();
}
}
View Code
控制台
2.2.2 异步创建
import org.apache.zookeeper.*;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/12.*/
public class ZookeeperTestCreateNodeAsync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "192.168.1.8:2181";private static final String PREFIX_ASYNC = "/mytest-async-create-";public static void main(String[] args) throwsIOException, InterruptedException {
ZooKeeper zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestCreateNodeAsync());
System.out.println("state:"+zooKeeper.getState());
countDownLatch.await();
zooKeeper.create(PREFIX_ASYNC,"".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,new IStringCallBack(), "my test text...1");
zooKeeper.create(PREFIX_ASYNC,"".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,new IStringCallBack(), "my test text...2");
zooKeeper.create(PREFIX_ASYNC,"".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,new IStringCallBack(), "my test text...3");
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState())
countDownLatch.countDown();
}
}class IStringCallBack implementsAsyncCallback.StringCallback {public void processResult(intrc, String path, Object ctx, String name) {
System.out.println("rc:"+rc+",path:"+path+",ctx:"+ctx+"name,"+name);
}
}
View Code
控制台
说明:同步需要关注接口异常,异步接口不会反回异常,而是在回调函数中通过result code体现
2.3 创建节点
只允许删除叶子节点,即如果节点包含子节点,则必须先删除子节点才能删除本节点。
2.3.1 同步方式
import org.apache.zookeeper.*;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/12.*/
public class ZookeeperTestDeleteNodeSync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "192.168.1.8:2181";private static final String PREFIX_SYNC = "/mytest-sync-delete-";public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestDeleteNodeSync());
countDownLatch.await();
zooKeeper.create(PREFIX_SYNC,"mydelete".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zooKeeper.create(PREFIX_SYNC+ "/c1", "mydelete".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);try{
zooKeeper.delete(PREFIX_SYNC,-1);
}catch(Exception e) {
System.out.println("faile to delete path:"+PREFIX_SYNC);
}
zooKeeper.delete(PREFIX_SYNC+ "/c1", -1);
System.out.println("success to delete /c1");
zooKeeper.delete(PREFIX_SYNC ,-1);
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath())
countDownLatch.countDown();
}
}
}
View Code
控制台
2.3.2 异步方式
import org.apache.zookeeper.*;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/12.*/
public class ZookeeperTestDeleteNodeASync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "192.168.1.8:2181";private static final String PREFIX_SYNC = "/mytest-async-delete-";public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestDeleteNodeASync());
countDownLatch.await();
zooKeeper.create(PREFIX_SYNC,"mydelete".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zooKeeper.create(PREFIX_SYNC+ "/c1", "mydelete".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zooKeeper.delete(PREFIX_SYNC ,-1, new IVoidCallback(), null);
zooKeeper.delete(PREFIX_SYNC+ "/c1", -1, new IVoidCallback(), null);
zooKeeper.delete(PREFIX_SYNC ,-1, new IVoidCallback(), null);
System.out.println("success to delete /c1");
zooKeeper.delete(PREFIX_SYNC ,-1);
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath())
countDownLatch.countDown();
}
}
}class IVoidCallback implementsAsyncCallback.VoidCallback {public void processResult(intrc, String path, Object ctx) {
System.out.println(rc+ "::" + path + "::" +ctx);
}
}
View Code
控制台
2.4 获取子节点
2.4.1 同步方式
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Id;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestGetChildrenNodeSync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "192.168.1.8:2181";private static final String PREFIX_SYNC = "/mytest-sync-getChild-";private staticZooKeeper zooKeeper ;public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestGetChildrenNodeSync());
countDownLatch.await();
zooKeeper.create(PREFIX_SYNC,"".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zooKeeper.create(PREFIX_SYNC+ "/c1", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println(zooKeeper.getChildren(PREFIX_SYNC,true));
zooKeeper.create(PREFIX_SYNC+ "/c2", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println(zooKeeper.getChildren(PREFIX_SYNC,true));
Thread.sleep(1000);
zooKeeper.create(PREFIX_SYNC+ "/c3", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println(zooKeeper.getChildren(PREFIX_SYNC,true));
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}else if(Event.EventType.NodeChildrenChanged ==event.getType()){try{
System.out.println("get Child:" + zooKeeper.getChildren(event.getPath(), true));
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
View Code
控制台
Watcher通知是一次性的,即一旦触发一次通知后,该Watcher就失效了,因此客户端需要反复注册Watcher,即程序中在process里面又注册了Watcher,zooKeeper.getData(path,watch,stat), 第二个参数值设为true则添加一次监听, 否则,将无法获取c3节点的创建而导致子节点变化的事件。
2.4.2 异步方式
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.List;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestGetChildrenNodeASync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "192.168.1.8:2181";private static final String PREFIX_SYNC = "/mytest-async-getChild-";private staticZooKeeper zooKeeper ;public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestGetChildrenNodeASync());
countDownLatch.await();
zooKeeper.create(PREFIX_SYNC,"".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zooKeeper.create(PREFIX_SYNC+ "/c1", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zooKeeper.getChildren(PREFIX_SYNC,true, new IChildren2Callback(), null);
zooKeeper.create(PREFIX_SYNC+ "/c2", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zooKeeper.getChildren(PREFIX_SYNC,true, new IChildren2Callback(), null);
Thread.sleep(1000);
zooKeeper.create(PREFIX_SYNC+ "/c3", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zooKeeper.getChildren(PREFIX_SYNC,true, new IChildren2Callback(), null);
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}else if(Event.EventType.NodeChildrenChanged ==event.getType()){try{
System.out.println("get Child:" + zooKeeper.getChildren(event.getPath(), true));
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}class IChildren2Callback implementsAsyncCallback.Children2Callback {public void processResult(int rc, String path, Object ctx, Listchildren, Stat stat) {
System.out.println(rc+ "::" + path + "::" +ctx +"::" + children + "::" +stat);
}
}
View Code
控制台
2.5 节点的数据获取
2.5.1 同步方式
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestGetNodeDataSync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "10.0.40.10:2181";private static final String PREFIX_SYNC = "/mytest-sync-getData4-";private staticZooKeeper zooKeeper ;private static final Stat stat = newStat();public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestGetNodeDataSync());
countDownLatch.await();
zooKeeper.create(PREFIX_SYNC,"hellodata".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("the data of node:" + new String(zooKeeper.getData(PREFIX_SYNC, true, stat)));
System.out.println("czxid::"+stat.getCzxid()+",mzxid::" + stat.getMzxid() + ",version::" +stat.getVersion());
zooKeeper.setData(PREFIX_SYNC,"hello2data".getBytes(), -1);
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}else if(Event.EventType.NodeDataChanged ==event.getType()){try{
System.out.println("the data of:" + event.getPath() + " is::" + new String(zooKeeper.getData(event.getPath(), true, stat)));
System.out.println("watch czxid::"+stat.getCzxid()+",mzxid::" + stat.getMzxid() + ",version::" +stat.getVersion());
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
View Code
控制台
2.5.2 异步方式
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestGetNodeDataASync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "10.0.40.10:2181";private static final String PREFIX_SYNC = "/mytest-async-getData8-";private staticZooKeeper zooKeeper ;private static final Stat stat = newStat();public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestGetNodeDataASync());
countDownLatch.await();
zooKeeper.create(PREFIX_SYNC,"hello7data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zooKeeper.getData(PREFIX_SYNC,true, new IDataCallback(), null);for(int i=0; i<3; i++){
zooKeeper.setData(PREFIX_SYNC,"hello6data".getBytes(), -1);
}
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}else if(Event.EventType.NodeDataChanged ==event.getType()){try{
zooKeeper.getData(PREFIX_SYNC,true, new IDataCallback(), null);
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}class IDataCallback implementsAsyncCallback.DataCallback {public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
System.out.println("watch rc::" + rc + ", path::" + path + ", ctx::" + ctx +", data::" + newString(data));
System.out.println("watch czxid::"+stat.getCzxid()+",mzxid::" + stat.getMzxid() + ",version::" +stat.getVersion());
}
}
View Code
控制台
2.6 更新数据
在更新数据时,setData方法存在一个version参数,其用于指定节点的数据版本,表明本次更新操作是针对指定的数据版本进行的,但是,在getData方法中,并没有提供根据指定数据版本来获取数据的接口,那么,这里为何要指定数据更新版本呢,这里方便理解,可以等效于CAS(compare and swap),对于值V,每次更新之前都会比较其值是否是预期值A,只有符合预期,才会将V原子化地更新到新值B。Zookeeper的setData接口中的version参数可以对应预期值,表明是针对哪个数据版本进行更新,假如一个客户端试图进行更新操作,它会携带上次获取到的version值进行更新,而如果这段时间内,Zookeeper服务器上该节点的数据已经被其他客户端更新,那么其数据版本也会相应更新,而客户端携带的version将无法匹配,无法更新成功,因此可以有效地避免分布式更新的并发问题。
2.6.1 同步方式
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestSetNodeDataSync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "10.0.40.10:2181";private static final String PREFIX_SYNC = "/mytest-sync-setData2-";private staticZooKeeper zooKeeper ;public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestSetNodeDataSync());
countDownLatch.await();
zooKeeper.create(PREFIX_SYNC,"hello6data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("the data of node:" + new String(zooKeeper.getData(PREFIX_SYNC, true, null)));
Stat stat= zooKeeper.setData(PREFIX_SYNC, "hello6data".getBytes(), -1);
System.out.println("czxid::"+stat.getCzxid()+",mzxid::" + stat.getMzxid() + ",version::" +stat.getVersion());
Stat stat2= zooKeeper.setData(PREFIX_SYNC, "hello6data".getBytes(), stat.getVersion());
System.out.println("czxid::"+stat2.getCzxid()+",mzxid::" + stat2.getMzxid() + ",version::" +stat2.getVersion());try{
zooKeeper.setData(PREFIX_SYNC,"hello6data".getBytes(), stat.getVersion());
}catch(Exception e) {
System.out.println("exception: " +e);
}
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}else if(Event.EventType.NodeDataChanged ==event.getType()){try{
System.out.println("watch the data of:" + event.getPath() + " is::" + new String(zooKeeper.getData(event.getPath(), true, null)));
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
View Code
控制台
2.6.2 异步方式
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestSetNodeDataASync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "10.0.40.10:2181";private static final String PREFIX_SYNC = "/mytest-async-setData4-";private staticZooKeeper zooKeeper ;public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestSetNodeDataASync());
countDownLatch.await();
zooKeeper.create(PREFIX_SYNC,"hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zooKeeper.setData(PREFIX_SYNC,"hello2".getBytes(), -1, new StatCallback(), null);
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}
}
}
}class StatCallback implementsAsyncCallback.StatCallback {public void processResult(intrc, String path, Object ctx, Stat stat) {
System.out.println("rc:"+rc + ", path:" + path + ",ctx:" + ctx + ", stat:" +stat);
}
}
View Code
控制台
rc(ResultCode)为0,表明成功更新节点数据。
2.7 检查节点是否存在
2.7.1 同步方式
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestExistSync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "10.0.40.10:2181";private static final String PREFIX_SYNC = "/mytest-sync-exist-";private staticZooKeeper zooKeeper ;public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestExistSync());
countDownLatch.await();
zooKeeper.exists(PREFIX_SYNC,true);
zooKeeper.create(PREFIX_SYNC,"hello6data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zooKeeper.setData(PREFIX_SYNC,"hello6data".getBytes(), -1);
zooKeeper.delete(PREFIX_SYNC,-1);
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){try{if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}else if(Event.EventType.NodeDataChanged ==event.getType()){
System.out.println("node " + event.getPath() + " changed.");
zooKeeper.exists(event.getPath(),true);
}else if(Event.EventType.NodeCreated ==event.getType()){
System.out.println("node " + event.getPath() + " created.");
zooKeeper.exists(event.getPath(),true);
}else if(Event.EventType.NodeDeleted ==event.getType()){
System.out.println("node " + event.getPath() + " deleted.");
zooKeeper.exists(event.getPath(),true);
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
View Code
控制台
2.7.2 异步方式
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestExistASync implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "10.0.40.10:2181";private static final String PREFIX_SYNC = "/mytest-async-exist8-";private staticZooKeeper zooKeeper ;public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestExistASync());
countDownLatch.await();
zooKeeper.exists(PREFIX_SYNC,true, new IStaCallback(), null);
zooKeeper.create(PREFIX_SYNC,"111".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zooKeeper.setData(PREFIX_SYNC,"222".getBytes(), -1);//判断存在 并加监听
zooKeeper.exists(PREFIX_SYNC + "/c2", true, new IStaCallback(), null);
zooKeeper.create(PREFIX_SYNC+ "/c2", "111".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zooKeeper.delete(PREFIX_SYNC+ "/c2", -1);//zooKeeper.exists(PREFIX_SYNC , true, new IStaCallback(), null);//上面修改数据 那步 对PREFIX_SYNC添加了一个监听
zooKeeper.delete(PREFIX_SYNC, -1);
Thread.sleep(Integer.MAX_VALUE);
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){try{if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}else if(Event.EventType.NodeDataChanged ==event.getType()){
System.out.println("node " + event.getPath() + " changed.");
zooKeeper.exists(event.getPath(),true, new IStaCallback(), null);
}else if(Event.EventType.NodeCreated ==event.getType()){
System.out.println("node " + event.getPath() + " created.");
zooKeeper.exists(event.getPath(),true, new IStaCallback(), null);
}else if(Event.EventType.NodeDeleted ==event.getType()){
System.out.println("node " + event.getPath() + " deleted.");
zooKeeper.exists(event.getPath(),true, new IStaCallback(), null);
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}class IStaCallback implementsAsyncCallback.StatCallback {public void processResult(intrc, String path, Object ctx, Stat stat) {
System.out.println("rc:" + rc + ",path: " + path + ",ctx:" + ctx + ", stat:" +stat);
}
}
View Code
控制台
rc:-101,path: /mytest-async-exist8-,ctx:null, stat:nullnode/mytest-async-exist8-created.
rc:0,path: /mytest-async-exist8-,ctx:null, stat:8590337352,8590337352,1526279675044,1526279675044,0,0,0,0,3,0,8590337352node/mytest-async-exist8-changed.
rc:0,path: /mytest-async-exist8-,ctx:null, stat:8590337352,8590337353,1526279675044,1526279675095,1,0,0,0,3,0,8590337352rc:-101,path: /mytest-async-exist8-/c2,ctx:null, stat:nullnode/mytest-async-exist8-/c2 created.
rc:0,path: /mytest-async-exist8-/c2,ctx:null, stat:8590337354,8590337354,1526279675128,1526279675128,0,0,0,0,3,0,8590337354node/mytest-async-exist8-/c2 deleted.
rc:-101,path: /mytest-async-exist8-/c2,ctx:null, stat:nullnode/mytest-async-exist8-deleted.
rc:-101,path: /mytest-async-exist8-,ctx:null, stat:null
View Code
rc:-101 节点不存在去
2.8 权限相关
zookeeper使用ACL机制来实现权限控制, ACL机制主要分为3个方面,权限模式,权限ID和权限
2.8.1 权限模式
1) IP
ip模式是指权限针对这个ip而设置的,比如"ip:192.168.0.6",即允许这个ip访问数据节点
2) digest
digest模式是最常用的一种模式,形如"username:password"的方式。
3) world
该模式对所有用户开放
4) super
超级管理员模式。需要在zkServer.sh中配置,形如"super:password" ,需要重启服务器
2.8.2 权限ID
根据不同模式 授权给的不同对象, ip模式为ip地址, digest模式为username
2.8.2 权限
即允许的操作 CRUD等
2.8.4 删除节点+权限
import org.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.concurrent.CountDownLatch;/*** @Author: rocky
* @Date: Created in 2018/5/13.*/
public class ZookeeperTestAcl implementsWatcher {private static final CountDownLatch countDownLatch = new CountDownLatch(1);private static final String ADDRESS = "10.0.40.10:2181";private static final String PREFIX_SYNC = "/mytest-sync-acl-";private staticZooKeeper zooKeeper ;public static void main(String[] args) throwsIOException, InterruptedException, KeeperException {try{
zooKeeper= new ZooKeeper(ADDRESS, 5000, newZookeeperTestAcl());
countDownLatch.await();
zooKeeper.addAuthInfo("digest", "true".getBytes());
zooKeeper.create(PREFIX_SYNC,"111".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT);
zooKeeper.create(PREFIX_SYNC+"/c2", "222".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL);
ZooKeeper zk2= new ZooKeeper(ADDRESS, 5000, null);try{
zk2.delete(PREFIX_SYNC+"/c2", -1);
}catch(Exception e) {
System.out.println("delete exception: " +e);
}
ZooKeeper zk3= new ZooKeeper(ADDRESS, 5000, null);
zk3.addAuthInfo("digest", "true".getBytes());
zk3.delete(PREFIX_SYNC+"/c2", -1);
System.out.println("delete mytest-sync-acl-/c2 success");
ZooKeeper zk4= new ZooKeeper(ADDRESS, 5000, null);
zk4.delete(PREFIX_SYNC,-1);
System.out.println("delete mytest-sync-acl- success");
Thread.sleep(Integer.MAX_VALUE);
}catch(Exception e) {
System.out.println("exception ::" +e);
}
}public voidprocess(WatchedEvent event) {if(Event.KeeperState.SyncConnected ==event.getState()){if(Event.EventType.None == event.getType() && null ==event.getPath()){
countDownLatch.countDown();
}
}
}
}
View Code
控制台
说明:
可以看到,第一次我们使用无权限的zk2去删除,显然会报错,第二次我们使用带权限的zk3去操作,子节点被删除成功,但是当我们使用zk4去执行删除操作的时候并没有指定任何权限,依然能够删除其父节点,说明zk在进行删除操作的时候,其权限的作用范围是其子节点。也就是说,当我们对一个节点添加了权限之后我们依然可以随意删除该节点但是对于这个节点的子节点,就必须拥有相应的权限才能删除。而且zk原生api不支持递归删除,即在存在子节点的情况下,不允许删除其父节点。