一、简介
在文章 zookeeper使用(一)--简介与安装中,我们介绍了zookeeper相关知识及安装方法。
在文本,将介绍zookeeper的常用命令,以及在java中的基本操作(包括原生的zookeeper和包装后的ZkClient)。
二、常用命令
1、启动、停止服务
./zkServer.sh start[stop]
2、连接服务
./zkCli.sh -server ip:port
3、清理历史数据、包括事务日志谁的和快照数据文件
./zkCleanup.sh
4、设置zookeeper的环境变量
./zkEnv.sh
5、创建节点
create [-s] [-e] path data acl
其中,-s指顺序节点,-e指临时节点,不添加-s和-e时,创建的是持久节点。acl是权限控制,不添加时,无权限控制。
6、查看子节点
ls path
7、获取指定节点的数据内容和属性信息
get path
8、更新节点数据内容
set path data
9、删除节点
delete path
10、递归删除节点
rmr path
三、原生zookeeper的java客户端使用
1、添加maven依赖
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
2、代码实例
public class ZookeeperMain {
public static void main(String[] args) throws Exception {
String connectStr = "127.0.0.1:2181"; //连接地址,后可跟目录,如127.0.0.1:2181/mydata
Watcher watcher = new SimpleWatcher(); //事件监听器
int sessionTimeout = 10000; //会话超时时间,单位是毫秒
ZooKeeper zookeeper = new ZooKeeper(connectStr,sessionTimeout,watcher); //创建会话
System.out.println("zookeeper state: "+ zookeeper.getState());
long sessionId = zookeeper.getSessionId(); //会话id ,用于重连
byte[] sessionPasswd = zookeeper.getSessionPasswd(); //会话密码,用于重连
TimeUnit.SECONDS.sleep(8);
System.out.println("zookeeper state : "+zookeeper.getState());
zookeeper = new ZooKeeper(connectStr,sessionTimeout,watcher,sessionId,sessionPasswd); //重新连接
System.out.println("zookeeper state : "+zookeeper.getState());
//同步创建节点
String m1 = zookeeper.create("/m1","mv1".getBytes("utf-8"), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
//异步创建节点
zookeeper.create("/m2", "mv2".getBytes("utf-8"), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT
, new AsyncCallback.StringCallback() {
public void processResult(int rc, String path, Object ctx, String name) {
System.out.println("异步创建节点成功 rc:"+rc+ " path:"+path+" ctx:"+ctx+" name:"+name);
}
},"context");
//同步获取子节点
List<String> children = zookeeper.getChildren("/",watcher);
System.out.println("同步获取子节点:"+children);
//异步获取子节点
zookeeper.getChildren("/", watcher, new AsyncCallback.Children2Callback() {
public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
System.out.println("异步获取子节点:"+children);
}
},null);
//同步获取节点的值
Stat stat = new Stat();
byte[] dataByte = zookeeper.getData("/m1",watcher,stat);
String data = new String(dataByte,"utf-8");
System.out.println("同步获取节点的值 m1 :"+data);
//异步获取节点的值
zookeeper.getData("/m1", watcher, new AsyncCallback.DataCallback() {
public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
try {
System.out.println("异步获取节点的值 m1 :"+new String(data,"utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
},null);
//同步更新值
zookeeper.setData("/m1","nm1".getBytes("utf8"),-1);
//异步更新值
zookeeper.setData("/m1", "nnm1".getBytes("utf8"), -1, new AsyncCallback.StatCallback() {
public void processResult(int rc, String path, Object ctx, Stat stat) {
if(rc==0){
System.out.println("异步更新值成功 ");
}
}
},null);
//删除节点
zookeeper.delete("/m1",-1);
//检测节点是否存在
Stat existStat = zookeeper.exists("/m1",watcher);
if(null== existStat){
System.out.println("节点不存在");
}
//权限控制
ZooKeeper zk = new ZooKeeper(connectStr,sessionTimeout,watcher);
zk.addAuthInfo("digest","pass".getBytes("utf8"));
String m6 = zk.create("/m6","mv6".getBytes("utf-8"), ZooDefs.Ids.CREATOR_ALL_ACL,CreateMode.PERSISTENT); //创建有权限的节点
byte[] byteResult = zk.getData("/m6",watcher,stat); //有权限读取
String result = new String(byteResult,"utf-8");
System.out.println("result with auth:"+result);
try{
byteResult = zookeeper.getData("/m6",watcher,stat); //无权限读取
result = new String(byteResult,"utf-8");
System.out.println("result without auth:"+result);
}catch (Exception e){
e.printStackTrace();
}
TimeUnit.HOURS.sleep(1);
}
static class SimpleWatcher implements Watcher{ //事件监听器,客户端注册后,当事件发生时,会通知客户端
public void process(WatchedEvent event) {
System.out.println("event is :"+event);
}
}
}
输出:
zookeeper state: CONNECTING
event is :WatchedEvent state:SyncConnected type:None path:null
zookeeper state : CONNECTED
zookeeper state : CONNECTING
event is :WatchedEvent state:SyncConnected type:None path:null
同步获取子节点:[ m6]
异步获取子节点:[ m6]
同步获取节点的值 m1 :mv1
异步获取节点的值 m1 :mv1
event is :WatchedEvent state:SyncConnected type:NodeDataChanged path:/m1
异步更新值成功
event is :WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/
节点不存在
event is :WatchedEvent state:SyncConnected type:None path:null
result with auth:mv6
四、基于开源zookeeper的java客户端ZkClient使用
ZkClient是对Zoookeeper客户端的包装,包装自动序列化和反序列化、通过Listener进行监听等。
1、添加maven依赖
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
2、代码实例
public class ZkClientMain {
public static void main(String[] args) throws Exception {
ZkClient zkClient = new ZkClient("127.0.0.1:2181",5000); //创建会话
zkClient.subscribeChildChanges("/", new IZkChildListener() { //监听子节点变化
public void handleChildChange(String s, List<String> list) throws Exception {
System.out.println("parent path: "+ s+ " now children is:"+list);
}
});
zkClient.create("/c1","cd1", CreateMode.PERSISTENT); //创建节点
List<String> children = zkClient.getChildren("/");//读取子节点
System.out.println("children : "+children);
String cv = zkClient.readData("/c1"); //读取节点数据
System.out.println("value of c1 :"+cv);
zkClient.subscribeDataChanges("/c1", new IZkDataListener() { //监听节点变化
public void handleDataChange(String s, Object o) throws Exception {
System.out.println(s+" data change :"+o);
}
public void handleDataDeleted(String s) throws Exception {
System.out.println(s+" data delete");
}
});
zkClient.writeData("/c1","nncv1"); //更新节点数据
System.out.println("value of c1 :"+zkClient.readData("/c1"));
zkClient.delete("/c1"); //删除节点数据
boolean existFlag = zkClient.exists("/c1"); //判断节点是否存在
if(!existFlag){
System.out.println("/c1 节点不存在");
}
TimeUnit.HOURS.sleep(1);
}
}
输出:
children : [c1]
parent path: / now children is:[c1]
value of c1 :cd1
value of c1 :nncv1
/c1 data change :nncv1
/c1 节点不存在
/c1 data delete
parent path: / now children is:[]