读《分布式一致性原理》JAVA客户端API操作2
Posted duan2
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了读《分布式一致性原理》JAVA客户端API操作2相关的知识,希望对你有一定的参考价值。
创建节点
通过客户端API来创建一个数据节点,有一下两个接口:
public String create(final String path, byte data[], List<ACL> acl,
CreateMode createMode)
public void create(final String path, byte data[], List<ACL> acl,
CreateMode createMode, StringCallback cb, Object ctx)
这两个接口分别是同步和异步的方式创建节点
需要注意的是无论是同步还是异步创建节点,zookeeper都不支持递归创建,即在不存在父节点的情况下创建一个子节点
。另外如果一个节点已经存在了,那么再创建同名节点时会抛出异常:NodeExistException
目前,节点的内容只支持byte[]数组类型,也就是说zookeeper不负责对象序列化,需要开发者自己讲内容进行序列化与反序列化。
对已字符串直接调用getByte就行。对于其他复杂对象,可以使用序列化工具来进行。
关于权限控制,如果你的应用场景中没有复杂的权限要求,那么直接调用I Ids.OPEN_ACL_UNSAFE,这表明之后对这个节点的任何操作不受权限控制。
使用API创建一个节点:
package znode;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import session.CreateZookeeper;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.KeeperState;
public class CreateZnode implements Watcher{
public static CountDownLatch connectedSemaphore = new CountDownLatch(1);
@Override
public void process(WatchedEvent event) {
System.out.println("receive watched event:"+event);
if (KeeperState.SyncConnected==event.getState()) {
connectedSemaphore.countDown();
}
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper = new ZooKeeper("192.168.64.60", 5000, new CreateZookeeper());
connectedSemaphore.await();
String path1 = zooKeeper.create("/zk-test-ephemera-","".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("success create znode:"+path1);
String path2 = zooKeeper.create("/zk-test-ephemera-","".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("success create znode:"+path2);
}
}
上面两个片段使用同步方式创建节点:可以看出创建临时节点返回值就是传入的路劲
使用临时顺序节点返回值会自动加上一个数字
使用异步API创建节点
package znode;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.AsyncCallback.StringCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import session.CreateZookeeper;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.KeeperState;
public class CreateZnode2 implements Watcher{
public static CountDownLatch connectedSemaphore = new CountDownLatch(1);
@Override
public void process(WatchedEvent event) {
System.out.println("receive watched event:"+event);
if (KeeperState.SyncConnected==event.getState()) {
connectedSemaphore.countDown();
}
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper = new ZooKeeper("192.168.64.60", 5000, new CreateZookeeper());
connectedSemaphore.await();
zooKeeper.create("/zk-test-ephemera-","".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL
,new IStringCallback(),"I am context");
zooKeeper.create("/zk-test-ephemera-","".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL
,new IStringCallback(),"I am context");
zooKeeper.create("/zk-test-ephemera-","".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL
,new IStringCallback(),"I am context");
}
}
class IStringCallback implements AsyncCallback.StringCallback{
@Override
public void processResult(int rc, String path, Object ctx, String name) {
// TODO Auto-generated method stub
System.out.println("create path result: ["+rc+","+path+","+ctx+","+"real path name:"+name+"]");
}
}
和同步接口最大的区别在于,节点在创建的过程(包含网络通信和服务端的创建过程),是异步的。而且我们需要注意的是
同步创建过程时我们需要关注接口抛出的异常,而在异步接口中,是不会抛出异常的,所有的异常都会在回调函数中通过Result Code来体现。
删除节点
public void delete(final String path, int version)
public void delete(final String path, int version, VoidCallback cb,
Object ctx)
这里列出的两个API是同步和异步的删除接口,API方法的参数说明如表5-5所示。
删除节点和更新节点的操作非常相似,在zookeeper中只允许删除叶子节点。也就是说,如果一个节点存在子节点的话
那么这个节点将无法直接删除,必须先删除其所有子节点。
读取数据
读取数据,包含子节点列表的获取和节点数据的获取。
1.getChildren
首先我们先看看注册watcher。如果zookeeper客户端获取到指定节点的子节点列表后,还需要订阅这个子节点列表的变化通知,
那么就可以通过注册一个Watcher来实现。当有子节点添加或删除时,服务端就会向客户端发送一个NodeChildrenChange的事件。
需要注意的是服务端向客户端发送事件通知时是不包含最新的节点列表的。是需要客户端主动重新获取的。
Stat,stat记录一个节点的基本属性信息。创建时的事务ID(cZxid),最后一次修改的事务ID(mZxid)和节点数据内容的长度
dataLength,我们可以将一个旧的stat变量传入,该stat会在执行过程中,被来自服务端响应的心的stat的替换掉。
package getchildren;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
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.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
public class GetChildren1 implements Watcher {
public static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk = null;
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected==event.getState()) {
if (EventType.None.getIntValue()==event.getState().getIntValue()&&null==event.getPath()) {
connectedSemaphore.countDown();
}else if (event.getType()==EventType.NodeChildrenChanged) {
try {
System.out.println("ReGetChild:"+zk.getChildren(event.getPath(), true));
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
String path = "/zk-book";
zk = new ZooKeeper("192.168.64.60:2181", 5000, new GetChildren1());
connectedSemaphore.await();
zk.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(path+"/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
List<String> children = zk.getChildren(path, true);
System.out.println(children);
zk.create(path+"/c2", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
Thread.sleep(Integer.MAX_VALUE);;
}
}
使用异步API获取子节点列表
package getchildren;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.AsyncCallback;
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.data.Stat;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
public class GetChildren2 implements Watcher {
public static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk = null;
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected==event.getState()) {
if (EventType.None.getIntValue()==event.getState().getIntValue()&&null==event.getPath()) {
connectedSemaphore.countDown();
}else if (event.getType()==EventType.NodeChildrenChanged) {
try {
System.out.println("ReGetChild:"+zk.getChildren(event.getPath(), true));
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
String path = "/zk-book";
zk = new ZooKeeper("192.168.64.60:2181", 5000, new GetChildren2());
connectedSemaphore.await();
zk.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(path+"/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zk.getChildren(path, true, new IChildren2Callback(),"i am context");
zk.create(path+"/c2", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
Thread.sleep(Integer.MAX_VALUE);;
}
}
class IChildren2Callback implements AsyncCallback.Children2Callback{
@Override
public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
// TODO Auto-generated method stub
System.out.println("Get Children znode result: "+rc+","+path+","+ctx+","+children+","+stat);
}
}
getData
getData接口和上下文中的getChildren接口的用法相同,Watcher注册后,一旦节点的内容状态发生改变,zookeeper服务端会
向客户端发送一个NodeDataChanged的事件。API返回的结果类型时byte[].
使用同步AIP获取数据节点内容
package getdata;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
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.data.Stat;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import getchildren.GetChildren1;
public class GetData1 implements Watcher {
public static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk = null;
private static Stat stat = new Stat();
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected==event.getState()) {
if (EventType.None.getIntValue()==event.getState().getIntValue()&&null==event.getPath()) {
connectedSemaphore.countDown();
}else if (event.getType()==EventType.NodeDataChanged) {
try {
byte[] data = zk.getData(event.getPath(), true, stat);
System.out.println(new String(data));
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
String path = "/zk-book";
zk = new ZooKeeper("192.168.64.60:2181", 5000, new GetData1());
connectedSemaphore.await();
zk.create(path, "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println(zk.getData(path, true, stat));
zk.setData(path, "456".getBytes(), -1);
Thread.sleep(Integer.MAX_VALUE);;
}
}
数据内容或是数据版本发生变化,都胡出发服务端的NodeDataChanged通知。
异步API获取
package getdata;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.AsyncCallback;
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.data.Stat;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
public class GetData2 implements Watcher {
public static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk = null;
private static Stat stat = new Stat();
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected==event.getState()) {
if (EventType.None.getIntValue()==event.getState().getIntValue()&&null==event.getPath()) {
connectedSemaphore.countDown();
}else if (event.getType()==EventType.NodeDataChanged) {
zk.getData(event.getPath(), true, new IDataback(),null);
}
}
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
String path = "/zk-book";
zk = new ZooKeeper("192.168.64.60:2181", 5000, new GetData2());
connectedSemaphore.await();
zk.create(path, "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL );
zk.getData(path, true,new IDataback(),null);
zk.setData(path, "456".getBytes(), -1);
Thread.sleep(Integer.MAX_VALUE);;
}
}
class IDataback implements AsyncCallback.DataCallback{
@Override
public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
System.out.println(new String(data));
System.out.println(stat.getCzxid());
System.out.println(stat.getMzxid());
System.out.println(stat.getVersion());
}
}
以上是关于读《分布式一致性原理》JAVA客户端API操作2的主要内容,如果未能解决你的问题,请参考以下文章