【Free Style】ZooKeeper总结材料分享(四)
5.1.4 共享锁
共享锁在同一个进程中很容易实现,但是在跨进程或者在不同 Server 之间就不好实现了。Zookeeper 却很容易实现这个功能,实现方式也是需要获得锁的 Server 创建一个 EPHEMERAL_SEQUENTIAL 目录节点,然后调用 getChildren方法获取当前的目录节点列表中最小的目录节点是不是就是自己创建的目录节点,如果正是自己创建的,那么它就获得了这个锁,如果不是那么它就调用 exists(String path, boolean watch) 方法并监控 Zookeeper 上目录节点列表的变化,一直到自己创建的节点是列表中最小编号的目录节点,从而获得锁,释放锁很简单,只要删除前面它自己所创建的目录节点就行了。
5.2 典型应用场景二
利用Zookeeper实现某些分布式应用所必需的高级功能。所有功能均可以在客户端按固定的模式实现,不需要 Zookeeper的特殊支持,也希望 Zookeeper 社区能将这些具有固定实现模式的功能集成到 Zookeeper 客户端的程序库中,可以简化 Zookeeper 的使用并且还能使某些功能的实现标准化。
即便 Zookeeper 本身使用异步通知(asyn*** ous notifications),但却可以基于此构建同步的(syn*** ous)一致性原语,如队列和锁。你将看到 Zookeeper 实现这些功能是完全可能的,因为 Zookeeper 提供了强制的全序更新,并对外提供了保序接口。
注意下面的程序段试图采取最佳的编程实践,尤其是避免使用轮询(polling),定时器(timers)和其他任何可能造成“羊群效应(herd effect)”机制(“羊群效应”一般会带来网络流量的突增,限制系统的可扩展性)。
除了本文所列举的功能,我们还可以想象出其他很多实用的功能,比如可撤销的读写优先锁。本文提到的某些构建方式——比如锁,比较详细的阐述了使用 Zookepper 的关键点,其实你可以找到其他的例子,如事件处理和队列,但是,本节中的例子只是模拟相关的功能,在具体实践中需要考虑其他方面的因素。
指定的目录。
6.2.7 数据文件管理
1. 数据目录
ZK的数据目录包含两类文件:
l myid – 这个文件只包含一个数字,和server id对应。
l snapshot. – 按zxid先后顺序的生成的数据快照。
集群中的每台ZK server都会有一个用于惟一标识自己的id,有两个地方会使用到这个id:myid文件和zoo.cfg文件中。myid文件存储在dataDir目录中,指定了当前server的server id。在zoo.cfg文件中,根据server id,配置了每个server的ip和相应端口。Zookeeper启动的时候,读取myid文件中的server id,然后去zoo.cfg 中查找对应的配置。
zookeeper在进行数据快照过程中,会生成 snapshot文件,存储在dataDir目录中。文件后缀是zxid,也就是事务id。(这个zxid代表了zk触发快照那个瞬间,提交的最后一个事务id)。注意,一个快照文件中的数据内容和提交第zxid个事务时内存中数据近似相同。仅管如此,由于更新操作的幂等性,ZK还是能够从快照文件中恢复数据。数据恢复过程中,将事务日志和快照文件中的数据对应起来,就能够恢复最后一次更新后的数据了。
2. 事务日志目录
dataLogDir目录是ZK的事务日志目录,包含了所有ZK的事务日志。正常运行过程中,针对所有更新操作,在返回客户端“更新成功”的响应前,ZK会确保已经将本次更新操作的事务日志写到磁盘上,只有这样,整个更新操作才会生效。每触发一次数据快照,就会生成一个新的事务日志。事务日志的文件名是log.,zxid是写入这个文件的第一个事务id。
3. 文件管理
不同的zookeeper server生成的snapshot文件和事务日志文件的格式都是一致的(无论是什么环境,或是什么样的zoo.cfg 配置)。因此,如果某一天生产环境中出现一些古怪的问题,你就可以把这些文件下载到开发环境的zookeeper中加载起来,便于调试发现问题,而不会影响生产运行。另外,使用这些较旧的snapshot和事务日志,我们还能够方便的让ZK回滚到一个历史状态。
另外,ZK提供的工具类LogFormatter能够帮助可视化ZK的事务日志,帮助我们排查问题,关于事务日志的可以化,请查看这个文章《可视化zookeeper的事务日志》.
需要注意的一点是,zookeeper在运行过程中,不断地生成snapshot文件和事务日志,但是不会自动清理它们,需要管理员来处理。(ZK本身只需要使用最新的snapshot和事务日志即可)关于如何清理文件,上面章节“日常运维”有提到。
6.2.8 注意事项
1. 保持server事务列表一致
· 客户端使用的server地址列表必须和集群所有server的地址列表一致。(如果客户端配置了集群机器列表的子集的话,也是没有问题的,只是少了客户端的容灾。)
· 集群中每个server的zoo.cfg中配置机器列表必须一致。
2. 独立的事务日志输出
对于每个更新操作,ZK都会在确保事务日志已经写到磁盘后,才会返回客户端响应。因此事务日志的输出性能在很大程度上影响ZK的整体吞吐性能。强烈建议是给事务日志的输出分配一个单独的磁盘。
3. 配置合理的JVM堆大小
一个合理的JVM堆大小,如果设置太大,会让内存与磁盘进行交换,这将使ZK的性能大打折扣。例如一个4G内存的机器的,如果你把JVM的堆大小设置为4G或更大,那么会使频繁发生内存与磁盘空间的交换,通常设置成3G就可以了。当然,为了获得一个最好的堆大小值,在特定的使用场景下进行一些压力测试。
7 配置参数
参数名 | 说明 |
clientPort (配置文件中必须要有) | 客户端连接server的端口,即对外服务端口,一般设置为2181。 |
dataDir(配置文件中必须要有) | 存储快照文件snapshot的目录。默认情况下,事务日志也会存储在这里。建议同时配置参数dataLogDir,事务日志的写性能直接影响zk性能。 |
tickTime(配置文件中必须要有) | ZK中的一个时间单元。ZK中所有时间都是以这个时间单元为基础,进行整数倍配置的。例如,session的最小超时时间是2*tickTime。 |
dataLogDir | 事务日志输出目录。尽量给事务日志的输出配置单独的磁盘或是挂载点,这将极大的提升ZK性能。(No Java system property) |
globalOutstandingLimit | 最大请求堆积数。默认是1000。ZK运行的时候, 尽管server已经没有空闲来处理更多的客户端请求了,但是还是允许客户端将请求提交到服务器上来,以提高吞吐性能。当然,为了防止Server内存溢出,这个请求堆积数还是需要限制下的。 |
preAllocSize | 预先开辟磁盘空间,用于后续写入事务日志。默认是64M,每个事务日志大小就是64M。如果ZK的快照频率较大的话,建议适当减小这个参数。(Java system property:zookeeper.preAllocSize) |
snapCount | 每进行snapCount次事务日志输出后,触发一次快照(snapshot), 此时,ZK会生成一个snapshot.*文件,同时创建一个新的事务日志文件log.*。默认是100000.(真正的代码实现中,会进行一定的随机数处理,以避免所有服务器在同一时间进行快照而影响性能)(Java system property:zookeeper.snapCount) |
traceFile | 用于记录所有请求的log,一般调试过程中可以使用,但是生产环境不建议使用,会严重影响性能。(Java system property:?requestTraceFile) |
maxClientCnxns | 单个客户端与单台服务器之间的连接数的限制,是ip级别的,默认是60,如果设置为0,那么表明不作任何限制。请注意这个限制的使用范围,仅仅是单台客户端机器与单台ZK服务器之间的连接数限制,不是针对指定客户端IP,也不是ZK集群的连接数限制,也不是单台ZK对所有客户端的连接数限制。指定客户端IP的限制策略,这里有一个patch,可以尝试一下:(No Java system property) |
clientPortAddress | 对于多网卡的机器,可以为每个IP指定不同的监听端口。默认情况是所有IP都监听clientPort指定的端口。New in 3.3.0 |
minSessionTimeoutmaxSessionTimeout | Session超时时间限制,如果客户端设置的超时时间不在这个范围,那么会被强制设置为最大或最小时间。默认的Session超时时间是在2 * tickTime ~ 20 * tickTime这个范围 New in 3.3.0 |
fsync.warningthresholdms | 事务日志输出时,如果调用fsync方法超过指定的超时时间,那么会在日志中输出警告信息。默认是1000ms。(Java system property:fsync.warningthresholdms)New in 3.3.4 |
autopurge.purgeInterval | 在上文中已经提到,3.4.0及之后版本,ZK提供了自动清理事务日志和快照文件的功能,这个参数指定了清理频率,单位是小时,需要配置一个1或更大的整数,默认是0,表示不开启自动清理功能。(No Java system property) New in 3.4.0 |
autopurge.snapRetainCount | 这个参数和上面的参数搭配使用,这个参数指定了需要保留的文件数目。默认是保留3个。(No Java system property)New in 3.4.0 |
electionAlg | 在之前的版本中, 这个参数配置是允许我们选择leader选举算法,但是由于在以后的版本中,只会留下一种“TCP-based version of fast leader election”算法,所以这个参数目前看来没有用了,这里也不详细展开说了。(No Java system property) |
initLimit | Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许F在initLimit时间内完成这个工作。通常情况下,我们不用太在意这个参数的设置。如果ZK集群的数据量确实很大了,F在启动的时候,从Leader上同步数据的时间也会相应变长,因此在这种情况下,有必要适当调大这个参数了。(No Java system property) |
syncLimit | 在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。如果L发出心跳包在syncLimit之后,还没有从F那里收到响应,那么就认为这个F已经不在线了。注意:不要把这个参数设置得过大,否则可能会掩盖一些问题。(No Java system property) |
leaderServes | 默认情况下,Leader是会接受客户端连接,并提供正常的读写服务。但是,如果你想让Leader专注于集群中机器的协调,那么可以将这个参数设置为no,这样一来,会大大提高写操作的性能。(Java system property: zookeeper.leaderServes)。 |
server.x=[hostname]:nnnnn[:nnnnn] | 这里的x是一个数字,与myid文件中的id是一致的。右边可以配置两个端口,第一个端口用于F和L之间的数据同步和其它通信,第二个端口用于Leader选举过程中投票通信。 |
group.x=nnnnn[:nnnnn]weight.x=nnnnn | 对机器分组和权重设置,可以 参见这里(No Java system property) |
cnxTimeout | Leader选举过程中,打开一次连接的超时时间,默认是5s。(Java system property: zookeeper.cnxTimeout) |
zookeeper.DigestAuthenticationProvider | ZK权限设置相关,具体参见《使用super身份对有权限的节点进行操作》 和 《ZooKeeper权限控制》 |
skipACL | 对所有客户端请求都不作ACL检查。如果之前节点上设置有权限限制,一旦服务器上打开这个开头,那么也将失效。(Java system property:zookeeper.skipACL) |
forceSync | 这个参数确定了是否需要在事务日志提交的时候调用FileChannel.force来保证数据完全同步到磁盘。(Java system property:zookeeper.forceSync) |
jute.maxbuffer | 每个节点最大数据量,是默认是1M。这个限制必须在server和client端都进行设置才会生效。(Java system property:jute.maxbuffer) |
8 常用的四字指令
参数名 | 说明 |
conf | 输出server的详细配置信息。New in 3.3.0
$>echo conf|nc localhost 2181 |
cons | 输出指定server上所有客户端连接的详细信息,包括客户端IP,会话ID等。
$>echo cons|nc localhost 2181 |
crst | 功能性命令。重置所有连接的统计信息。New in 3.3.0 |
dump | 这个命令针对Leader执行,用于输出所有等待队列中的会话和临时节点的信息。 |
envi | 用于输出server的环境变量。包括操作系统环境和Java环境。 |
ruok | 用于测试server是否处于无错状态。如果正常,则返回“imok”,否则没有任何响应。 |
stat | 输出server简要状态和连接的客户端信息。 |
srvr | 和stat类似,New in 3.3.0
$>echo stat|nc localhost 2181 Latency min/avg/max: 0/0/1036 $>echo srvr|nc localhost 2181 |
srst | 重置server的统计信息。 |
wchs | 列出所有watcher信息概要信息,数量等:New in 3.3.0
$>echo wchs|nc localhost 2181 |
wchc | 列出所有watcher信息,以watcher的session为归组单元排列,列出该会话订阅了哪些path:New in 3.3.0
$>echo wchc|nc localhost 2181 |
wchp | 列出所有watcher信息,以watcher的path为归组单元排列,列出该path被哪些会话订阅着:New in 3.3.0
$>echo wchp|nc localhost 2181 注意,wchc和wchp这两个命令执行的输出结果都是针对session的,对于运维人员来说可视化效果并不理想,可以尝试将cons命令执行输出的信息整合起来,就可以用客户端IP来代替会话ID了,具体可以看这个实现:http://rdc.taobao.com/team/jm/archives/1450 |
mntr | 输出一些ZK运行时信息,通过对这些返回结果的解析,可以达到监控的效果。New in 3.4.0
$ echo mntr | nc localhost 2185 |
9 其它博文
9.1 ZooKeeper----Client端
http://www.cnblogs.com/ggjucheng/p/3376548.html
9.2 ZooKeeper 通信模型
http://www.cnblogs.com/ggjucheng/p/3376568.html
10 常见错误
& 问题1 通过shell脚本在每个机器上启动zookeeper的时候,可能会显示以下错误信息”
Can
not open channel to X at election address”J 答案 这是由于zoo.cfg文件中指定的其它zookeeper服务找不到所导致,所有机器的
zookeeper
服务启动后改错误信息提示将会消失
& 问题2 当一个节点启动zkServer.sh start
后,如果马上查询状态,会提示
”Error contacting service. It is probably not running.”
J 答案 是由于zoo.cfg文件中指定的其它zookeeper服务找不到所导致,所有机器的zookeeper服务启动后改错误信息提示将会消失
,
所有节点都起来后在查询就正常了
& 问题3 当一个节点启动zkServer.sh start
后,如果马上查询状态,会提示
”Error contacting service. It is probably not running.”
J
答案
& 问题4 ./zkServer.sh start 在3个节点中多已经启动,但用./zkServer.sh status查询时servers之间一直没有建立通讯,当然用./zkCli.sh –server IP:PORT
连接时也连不上J
答案 可能是因为java的权限导致,我试了下用root可以启动成功。最后用当前账号安装的jdk
,启动就成功了。
- 点赞
- 收藏
- 关注作者
评论(0)