转自:http://www.cnblogs.com/gpcuster/archive/2010/12/29/1921213.html
ZOOKEEPER解惑
今年年初的时候,写了一篇ZooKeeper的入门文章《初识ZooKeeper》,一直到这一周,才有时间将ZooKeeper整个源码通读了一遍。不能说完全理解了ZooKeeper的工作原理与细节,但是之前心中一直关于ZooKeeper的疑问都得到了解释。
现在网上关于ZooKeeper的文章很多,有介绍Leader选举算法的,有介绍ZooKeeper Server内部原理的,还有介绍ZooKeeper Client的。本文不打算再写类似的内容,而专注与解答读者对ZooKeeper的相关疑问。
ZOOKEEPER在客户端究竟做了什么事情
使用过ZooKeeper的读者都知道,初始化客户端的代码如下:
1
2
3
|
System.out.println( "Starting ZK:" );
zk = new ZooKeeper(address, 3000 , this );
System.out.println( "Finished starting ZK: " + zk);
|
完成客户段的初始化之后,就可以对ZooKeeper进行相应的操作了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
if (zk != null ) {
try {
Stat s = zk.exists(root, false );
if (s == null ) {
zk.create(root, new byte [ 0 ], Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
} catch (KeeperException e) {
System.out
.println( "Keeper exception when instantiating queue: "
+ e.toString());
} catch (InterruptedException e) {
System.out.println( "Interrupted exception" );
}
} |
虽然上面的代码看起来简单明了,但是ZooKeeper的客户端在后台默默做了许多事情:
1 与ZooKeeper服务端进行通信,包括:连接,发送消息,接受消息。
2 发送心跳信息,保持与ZooKeeper服务端的有效连接与Session的有效性。
3 错误处理,如果客户端当前连接的ZooKeeper服务端失效,自动切换到另一台有效的ZooKeeper服务端。
4 管理Watcher,处理异常调用和Watcher。
WATCHER的事件通知机制是如何实现的
看过Google的分布式锁机制Chubby论文会发现,ZooKeeper中多了一个事件订阅机制:Watcher。那么Watcher内部究竟是如何实现的呢?
其实,在ZooKeeper客户端中,有一个成员变量(ZKWatchManager)专门负责管理所有的Watcher,当用户使用如下代码时:
1
|
List<String> list = zk.getChildren(path, watcher); |
ZooKeeper会将这个Watcher存储在ZKWatchManager中,同时通知ZooKeeper服务器记录该Client对应的Session中的Path下注册的事件类型。当ZooKeeper服务器发生了指定的事件后,ZooKeeper服务器将通知ZooKeeper客户端,ZooKeeper客户端再从ZKWatchManager中找到对应的回调函数,并予以执行。
整个过程中,客户端存储事件的信息和Watcher的执行逻辑,服务端只存储事件的信息。
如何用好ZOOKEEPER客户端
每实例化一个ZooKeeper客户端,就开启了一个Session。ZooKeeper客户端是线程安全的,也可以认为它实现了连接池。
因此,每一个应用只需要实例化一个ZooKeeper客户端即可,同一个ZooKeeper客户端实例可以在不同的线程中使用。
除非你想同一个应用中开启多个Session,使用不同的Watcher,在这种情况下,才需要实例化多个ZooKeeper客户端。
ZOOKEEPER是否对ZNODE有大小限制
如果你仔细看过ZooKeeper的文档,会发现文档中对ZNode的大小做了限制,最大不能超过1M。
这个1M的大小限制在ZooKeeper的客户端和服务端都有限制:
客户端:
1
2
3
4
5
6
|
packetLen = Integer.getInteger( "jute.maxbuffer" , 4096 * 1024 );
int len = incomingBuffer.getInt();
if (len < 0 || len >= packetLen) {
throw new IOException( "Packet len" + len + " is out of range!" );
} |
服务端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
static public final int maxBuffer = determineMaxBuffer();
private static int determineMaxBuffer() {
String maxBufferString = System.getProperty( "jute.maxbuffer" );
try {
return Integer.parseInt(maxBufferString);
} catch (Exception e) {
return 0xfffff ;
}
} if (len < 0 || len > maxBuffer) {
throw new IOException( "Unreasonable length = " + len);
} |
可以看出,ZooKeeper确实对数据的大小有限制,默认就是1M,如果希望传输超过1M的数据,可以修改环境变量“jute.maxbuffer”即可。
为什么要限制ZOOKEEPER中ZNODE的大小
ZooKeeper是一套高吞吐量的系统,为了提高系统的读取速度,ZooKeeper不允许从文件中读取需要的数据,而是直接从内存中查找。
还句话说,ZooKeeper集群中每一台服务器都包含全量的数据,并且这些数据都会加载到内存中。同时ZNode的数据并支持Append操作,全部都是Replace。
所以从上面分析可以看出,如果ZNode的过大,那么读写某一个ZNode将造成不确定的延时;同时ZNode过大,将过快地耗尽ZooKeeper服务器的内存。这也是为什么ZooKeeper不适合存储大量的数据的原因。
如何提升ZOOKEEPER集群的性能
我们说性能,可以从两个方面去考虑:写入的性能与读取的性能。
由于ZooKeeper的写入首先需要通过Leader,然后这个写入的消息需要传播到半数以上的Fellower通过才能完成整个写入。所以整个集群写入的性能无法通过增加服务器的数量达到目的,相反,整个集群中Fellower数量越多,整个集群写入的性能越差。
ZooKeeper集群中的每一台服务器都可以提供数据的读取服务,所以整个集群中服务器的数量越多,读取的性能就越好。但是Fellower增加又会降低整个集群的写入性能。为了避免这个问题,可以将ZooKeeper集群中部分服务器指定为Observer。
更多关于ZooKeeper的文章请参考:http://www.cnblogs.com/gpcuster/tag/ZooKeeper/
相关推荐
apache-zookeeper-3.7.1 apache-zookeeper-3.7.1 apache-zookeeper-3.7.1 apache-zookeeper-3.7.1 apache-zookeeper-3.7.1 apache-zookeeper-3.7.1 apache-zookeeper-3.7.1 apache-zookeeper-3.7.1 apache-zookeeper...
#Zookeeper的日志可以用LogFormatter查看 ##命令方式如下 java -classpath .:slf4j-api-1.7.2.jar:zookeeper-3.4.6.jar org.apache.zookeeper.server.LogFormatter /var/lib/zookeeper/version-2/log.1 ##window...
zookeeper 3.6.3 源码
zookeeper linux 搭建流程,zookeeper linux 搭建流程zookeeper linux 搭建流程zookeeper linux 搭建流程。
zookeeper可视化工具
【BAT必备】zookeeper面试题【BAT必备】zookeeper面试题【BAT必备】zookeeper面试题【BAT必备】zookeeper面试题【BAT必备】zookeeper面试题【BAT必备】zookeeper面试题【BAT必备】zookeeper面试题【BAT必备】...
dubbo2.6.0 + Zookeeper3.4.9 + Zookeeper3.8.0 + Zookeeper3.7.1
linux下编译zookeeper3.7.0出的头文件和库: proto.h recordio.h zookeeper.h zookeeper.jute.h zookeeper_log.h zookeeper_version.h libzookeeper_mt.a libzookeeper_mt.la libzookeeper_mt.so libzookeeper_mt....
ZooKeeper 未授权访问【原理扫描】,zookeeper安全漏洞修复方法和操作步骤
修改 zookeeper 3.4.14 源码,添加黑、白名单功能。
Zookeeper可以进行集群的配置管理,名字服务,分布式锁,集群管理等等
zookeeper-3.4.8zookeeper-3.4.8zookeeper-3.4.8zookeeper-3.4.8
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、...
Zookeeper是一个分布式的服务框架,是树型的目录服务的数据存储,能做到集群管理数据 ,这里能很好的作为Dubbo服务的注册中心。 Dubbo能与Zookeeper做到集群部署,当提供者出现断电等异常停机时,Zookeeper注册中心...
针对zookeeper的安全漏洞,增加了对访问ip地址的限制。
注册中心 zookeeper-3.4.6
zookeeper windows
包含Zookeeper-3.4.10和Zookeeper-3.5.7的压缩包
zookeeper教程zookeeper教程zookeeper教程zookeeper教程zookeeper教程
zookeeper客户端 图形化界面zookeeper客户端 图形化界面zookeeper客户端 图形化界面zookeeper客户端 图形化界面zookeeper客户端 图形化界面