热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:读《分布式一致性原理》JAVA客户端API操作2

篇首语:本文由编程笔记#小编为大家整理,主要介绍了读《分布式一致性原理》JAVA客户端API操作2相关的知识,希望对你有一定的参考价值。创

篇首语:本文由编程笔记#小编为大家整理,主要介绍了读《分布式一致性原理》JAVA客户端API操作2相关的知识,希望对你有一定的参考价值。




创建节点

通过客户端API来创建一个数据节点,有一下两个接口:


public String create(final String path, byte data[], List acl,
CreateMode createMode)
public void create(final String path, byte data[], List 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
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 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中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • java多线程获取线程返回结果
    我们在使用java多线程编写相关业务代码时,往往有这样一种情况,某个线程依赖于其他线程执行结果。也就是说,我们需要在一个线程中获取另一个线程的信息。可以分为两种情况,一种是轮询,一 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 时域|波形_语音处理基于matlab GUI音频数据处理含Matlab源码 1734期
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了语音处理基于matlabGUI音频数据处理含Matlab源码1734期相关的知识,希望对你有一定的参考价值。 ... [详细]
author-avatar
WLII庾斌_787
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有