Zookeeper的API调用的同步和异步机制以及watcher机制总结
2017-09-25 15:53
316 查看
同步和异步调用
对于zookeeper的所有API调用都提供了正常的同步调用和异步调用两种类型的调用接口,比如zookeeper创建某个目录节点的接口为例:
同步调用接口:
String create(final String
path, byte
data[], List<ACL>
acl,
CreateMode createMode)
异步调用接口:
void create(finalString
path,bytedata[],List<ACL>
acl,
CreateMode createMode, StringCallback
cb, Object ctx)
--很明显异步调用接口比同步调用接口多了两个参数StringCallback cb,Object
ctx,其中最关键的是参数StringCallbackcb,这是异步调用回调入口的依赖对象。使用例子如下
zk.create(ZNODE_NAME,"mymaster20882".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL, myStringCallBack, "enroll master");
StringCallback myStringCallBack =
new StringCallback(){
@Override
public
voidprocessResult(intrc, String
path, Object ctx, String
name) {
业务代码………………
}
};
--很明显是创建了一个匿名的内部类的方式实现的,该匿名类实现了StringCallback接口,并重写了接口的processResult方法,整个异步回调机制类似watcher机制,都是客户端向服务端发送请求后不阻塞客户端线程,继续往后面执行代码,等服务端执行完客户端的请求后再往客户端发送执行结果,客户端通过非阻塞io发现可读事件,并把可读的执行结果写入waitingEvents队列,以便eventThread线程轮询调用相关的StringCallback对象的processResult方法。Zookeeper的watcher机制也是这样的流程,不同的是watcher机制的返回消息的事件类型是watcher,而异步api调用返回的消息事件类型是StringCallback。
虽然两者的实现机制流程是相似的,但是使用上属于不同维度,不冲突,在使用watcher的同时也能使用异步api调用。
Watcher监听机制的类型和永久性
Zookeeper的watcher机制分成两大类型:defaultWatcher 和非defaultWatcher
defaultWatcher
其中defaultWatcher是在创建zookeeper对象(也就是客户端) 时传入构造方法。而且所有路径节点的改变都会通知defaultWatcher。
非defaultWatcher
非defaultWatcher分成三类:
dataWatcher,existWatcher,childWatcher
它们是通过下面对应的api来注册watcher的
dataWatcher-> getData() --注意setData, delete方法是不能注册watcher的
existWatcher-> exists()
childWatcher-> getChildren()
--非defaultWatcher的watcher是一次性的,所有如果需要实现所谓的永久性监控就得在Watcher的回调方法process方法中重新注册watcher
注意:其实defaultWatcher和非defaultWatcher都是一次性的,所以如果要实现所谓的永久性监控,那就得在watcher的回调中重新注册,其中defaultWatcher的注册有点特别,不需要再明显在api指定watcher对象名,只需要对getData(),exists(),getChildren()中booleanwatch参数设置为true即可。
综合上面两个表,我们可以总结出各种写操作可以触发哪些watcher,如下表所示:
Watcher机制的用例说明
defaultWatcher的用例
1.首先创建watcher对象,使用匿名内部类的方式
Watcher myWatcher= new Watcher(){
@Override
public voidprocess(WatchedEvent event) {
// TODOAuto-generated method stub
System.out.println(event.getPath()+""+event.getType());
try {
zk.exists("/root", true);
} catch(KeeperException e) {
// TODOAuto-generated catch block
e.printStackTrace();
} catch(InterruptedException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
};
2.在创建zookeeper对象时传入构造方法
zk = newZooKeeper("127.0.0.1:2181", 5000, myWatcher);
3.在使用注册watcher的api时,如果选择注册defaultWatcher,那么需要选择参数中带有boolean watch参数的方法。比如
getData(Stringpath, boolean watch, Stat stat)
exists(Stringpath, boolean watch)
getChildren(Stringpath, boolean watch)
并且boolean watch设置为true,比如下面例子:
zk.exists("/root",false);
zk.setData("/root","mydata".getBytes(), -1);
4.如何所谓永久地使defaultWatcher进行watch
可以注意到第一步1中红色内容zk.exists("/root", true);
实际上就是在回调方法中重新注册了defaultWatcher
非defaultWatcher的用例
非defaultWatcher的使用跟defaultWatcher基本一样,也是第一步创建watcher匿名内部类和watcher对象。不同的是不用第二步,直接到第三步,只是第三步使用的注册api接口跟defaultWatcher不一样,使用的接口比如:
getData(finalString path, Watcher watcher, Stat stat)
exists(finalString path, Watcher watcher)
getChildren(finalString path, Watcher watcher)
第四步如何所谓永久地使用非defaultWatcher进行监控,其实跟上面的4是类似的,在回调方法中重新注册非defaultWatcher
利用zookeeper进行分布式加锁和master选举问题
所谓的利用zookeeper实现分布式加锁其实就是利用了create接口的并发安全性来实现,所有客户端都去创建临时节点 /distribute_lock 节点,但zookeeper保证最终只有一个客户端成功创建,那个客户端也即拥有了这把锁。
比如:
zk.create(ZNODE_NAME,"mymaster20882".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL, myStringCallBack, "enroll master");
--多个客户端去创建临时节点ZNODE_NAME,但是只有一个能成功。注意CreateMode.EPHEMERAL这表示创建的这个节点是个非永久性的节点,会话消失后就消失。通过异步回调对象myStringCallBack的回调方法获得create的最终状态结果,竞争失败的客户端将进行watcher注册,等到获得锁的客户端会话消失后去再次竞争分布式锁。用这种机制实现分布式加锁和master选举,至于create的服务端的并发安全性有zookeeper自身保证。
对于zookeeper的所有API调用都提供了正常的同步调用和异步调用两种类型的调用接口,比如zookeeper创建某个目录节点的接口为例:
同步调用接口:
String create(final String
path, byte
data[], List<ACL>
acl,
CreateMode createMode)
异步调用接口:
void create(finalString
path,bytedata[],List<ACL>
acl,
CreateMode createMode, StringCallback
cb, Object ctx)
--很明显异步调用接口比同步调用接口多了两个参数StringCallback cb,Object
ctx,其中最关键的是参数StringCallbackcb,这是异步调用回调入口的依赖对象。使用例子如下
zk.create(ZNODE_NAME,"mymaster20882".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL, myStringCallBack, "enroll master");
StringCallback myStringCallBack =
new StringCallback(){
@Override
public
voidprocessResult(intrc, String
path, Object ctx, String
name) {
业务代码………………
}
};
--很明显是创建了一个匿名的内部类的方式实现的,该匿名类实现了StringCallback接口,并重写了接口的processResult方法,整个异步回调机制类似watcher机制,都是客户端向服务端发送请求后不阻塞客户端线程,继续往后面执行代码,等服务端执行完客户端的请求后再往客户端发送执行结果,客户端通过非阻塞io发现可读事件,并把可读的执行结果写入waitingEvents队列,以便eventThread线程轮询调用相关的StringCallback对象的processResult方法。Zookeeper的watcher机制也是这样的流程,不同的是watcher机制的返回消息的事件类型是watcher,而异步api调用返回的消息事件类型是StringCallback。
虽然两者的实现机制流程是相似的,但是使用上属于不同维度,不冲突,在使用watcher的同时也能使用异步api调用。
Watcher监听机制的类型和永久性
Zookeeper的watcher机制分成两大类型:defaultWatcher 和非defaultWatcher
defaultWatcher
其中defaultWatcher是在创建zookeeper对象(也就是客户端) 时传入构造方法。而且所有路径节点的改变都会通知defaultWatcher。
非defaultWatcher
非defaultWatcher分成三类:
dataWatcher,existWatcher,childWatcher
它们是通过下面对应的api来注册watcher的
dataWatcher-> getData() --注意setData, delete方法是不能注册watcher的
existWatcher-> exists()
childWatcher-> getChildren()
--非defaultWatcher的watcher是一次性的,所有如果需要实现所谓的永久性监控就得在Watcher的回调方法process方法中重新注册watcher
注意:其实defaultWatcher和非defaultWatcher都是一次性的,所以如果要实现所谓的永久性监控,那就得在watcher的回调中重新注册,其中defaultWatcher的注册有点特别,不需要再明显在api指定watcher对象名,只需要对getData(),exists(),getChildren()中booleanwatch参数设置为true即可。
综合上面两个表,我们可以总结出各种写操作可以触发哪些watcher,如下表所示:
“/path” | “/path/child” | |||||
exists | getData | getChildren | exists | getData | getChildren | |
create(“/path”) | √ | √ | ||||
delete(“/path”) | √ | √ | √ | |||
setData(“/path”) | √ | √ | ||||
create(“/path/child”) | √ | √ | √ | |||
delete(“/path/child”) | √ | √ | √ | √ | ||
setData(“/path/child”) | √ | √ |
defaultWatcher的用例
1.首先创建watcher对象,使用匿名内部类的方式
Watcher myWatcher= new Watcher(){
@Override
public voidprocess(WatchedEvent event) {
// TODOAuto-generated method stub
System.out.println(event.getPath()+""+event.getType());
try {
zk.exists("/root", true);
} catch(KeeperException e) {
// TODOAuto-generated catch block
e.printStackTrace();
} catch(InterruptedException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
};
2.在创建zookeeper对象时传入构造方法
zk = newZooKeeper("127.0.0.1:2181", 5000, myWatcher);
3.在使用注册watcher的api时,如果选择注册defaultWatcher,那么需要选择参数中带有boolean watch参数的方法。比如
getData(Stringpath, boolean watch, Stat stat)
exists(Stringpath, boolean watch)
getChildren(Stringpath, boolean watch)
并且boolean watch设置为true,比如下面例子:
zk.exists("/root",false);
zk.setData("/root","mydata".getBytes(), -1);
4.如何所谓永久地使defaultWatcher进行watch
可以注意到第一步1中红色内容zk.exists("/root", true);
实际上就是在回调方法中重新注册了defaultWatcher
非defaultWatcher的用例
非defaultWatcher的使用跟defaultWatcher基本一样,也是第一步创建watcher匿名内部类和watcher对象。不同的是不用第二步,直接到第三步,只是第三步使用的注册api接口跟defaultWatcher不一样,使用的接口比如:
getData(finalString path, Watcher watcher, Stat stat)
exists(finalString path, Watcher watcher)
getChildren(finalString path, Watcher watcher)
第四步如何所谓永久地使用非defaultWatcher进行监控,其实跟上面的4是类似的,在回调方法中重新注册非defaultWatcher
利用zookeeper进行分布式加锁和master选举问题
所谓的利用zookeeper实现分布式加锁其实就是利用了create接口的并发安全性来实现,所有客户端都去创建临时节点 /distribute_lock 节点,但zookeeper保证最终只有一个客户端成功创建,那个客户端也即拥有了这把锁。
比如:
zk.create(ZNODE_NAME,"mymaster20882".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL, myStringCallBack, "enroll master");
--多个客户端去创建临时节点ZNODE_NAME,但是只有一个能成功。注意CreateMode.EPHEMERAL这表示创建的这个节点是个非永久性的节点,会话消失后就消失。通过异步回调对象myStringCallBack的回调方法获得create的最终状态结果,竞争失败的客户端将进行watcher注册,等到获得锁的客户端会话消失后去再次竞争分布式锁。用这种机制实现分布式加锁和master选举,至于create的服务端的并发安全性有zookeeper自身保证。
相关文章推荐
- Zookeeper-Watcher机制与异步调用原理
- Zookeeper-Watcher机制与异步调用原理
- Zookeeper-Watcher机制与异步调用原理
- 【转】Zookeeper-Watcher机制与异步调用原理
- Qt刷新机制的一些总结(Qt内部画的时候是相当于画在后台一个对象里,然后在刷新的时候调用bitblt统一画,调用window的api并不会影响到后面的那个对象)
- C#委托、同步调用、异步调用总结
- Linux下同步模式、异步模式、阻塞调用、非阻塞调用总结 .
- C++重写(override)、重载(overload)、重定义(redefine)以及虚函数调用机制【个人总结】
- 调用机制:回调函数、同步调用、异步调用
- Linux下同步模式、异步模式、阻塞调用、非阻塞调用总结
- Symbian编程总结-基础篇-活动对象正解(4)-异步函数的同步调用
- java常见的几种调用机制(同步调用,异步调用,回调)
- [SAP ABAP开发技术总结]Function远程、同步、异步调用
- 【测试】Gunicorn , uWSGI同步异步测试以及应用场景总结
- 【测试】Gunicorn , uWSGI同步异步测试以及应用场景总结
- 分布式协调服务zookeeper02-zookeeper核心工作机制以及api代码演示
- 同步和异步关注的是消息通信机制,阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态
- Linux下同步模式、异步模式、阻塞调用、非阻塞调用总结
- 普通方法调用,Invoke,begininvoke三者的区别总结及异步与同步的区别总结
- Linux下同步模式、异步模式、阻塞调用、非阻塞调用总结