http://blog.csdn.net/jiyiqinlovexx/article/details/42687157
1、面临问题:
最近在基于Zookeeper开发一个分布式注册中心,包括两大功能: 配置信息的集中管理;服务的动态注册和发现。
这里面会面临一个问题: 平时在公司开发系统肯定都利用可视化配置界面将所有配置信息配置好了,如果要将这些配置信息部署到新的环境,或者更新已经存在的另一个环境的配置信息,该怎么办呢? 肯定不能把整个Zookeeper集群的文件夹都拷贝过去,删掉原有的完全替换为现在的新的这个。
2、解决方法:
解决这个问题需要明确Zookeeper的数据存储,如何对其进行移植。
配置Zookeeper的时候,会在zoo.cfg文件中指定dataDir路径,这个路径下会存放数据文件和日志文件,两个一起能够恢复Zookeeper集群数据。
一般来说数据文件名为:snapshot.x,而日志文件对应为:log.x+1。
要移植Zookeeper的数据,只需要将开发环境中这两个对应的文件拷贝上,完全替换现场环境的数据和日志文件即可。
---------------------------------------------------------------------------------------------------------------------------------------------------------------
以下转自 :@ni掌柜nileader@gmail.com 地址
数据文件管理
默认情况下,ZK的数据文件和事务日志是保存在同一个目录中,建议是将事务日志存储到单独的磁盘上。
1 数据目录
ZK的数据目录包含两类文件:
A、myid – 这个文件只包含一个数字,和serverid对应。
B、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和事务日志即可)关于如何清理文件,上面章节“日常运维”有提到。
日志清理
在使用zookeeper过程中,我们知道,会有dataDir和dataLogDir两个目录,分别用于snapshot和事务日志的输出(默认情况下只有dataDir目录,snapshot和事务日志都保存在这个目录中)。
ZK在完成若干次事务日志之后(在ZK中,凡是对数据有更新的操作,比如创建节点,删除节点或是对节点数据内容进行更新等,都会记录事务日志),ZK会触发一次快照(snapshot),将当前server上所有节点的状态以快照文件的形式dump到磁盘上去,即snapshot文件。这里的若干次事务日志是可以配置的,默认是100000,具体参看下文中关于配置参数“snapCount”的介绍。
考虑到ZK运行环境的差异性,以及对于这些历史文件,不同的管理员可能有自己的用途(例如作为数据备份),因此默认ZK是不会自动清理快照和事务日志,需要交给管理员自己来处理。
这里介绍4种清理日志的方法。在这4种方法中,推荐使用第一种方法,对于运维人员来说,将日志清理工作独立出来,便于统一管理也更可控。毕竟zk自带的一些工具并不怎么给力,这里是社区反映的两个问题:
https://issues.apache.org/jira/browse/ZOOKEEPER-957
http://zookeeper-user.578899.n2.nabble.com/PurgeTxnLog-td6304244.html
第一种,也是运维人员最常用的,写一个删除日志脚本,每天定时执行即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
以上这个脚本定义了删除对应两个目录中的文件,保留最新的60个文件,可以将他写到crontab中,设置为每天凌晨2点执行一次就可以了。
第二种,使用ZK的工具类PurgeTxnLog,它的实现了一种简单的历史文件清理策略,可以在这里看一下他的使用方法:http://zookeeper.apache.org/doc/r3.4.3/api/index.html,可以指定要清理的目录和需要保留的文件数目,简单使用如下:
-
java -cp zookeeper.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-log4j12-1.6.1.jar:lib/log4j-1.2.15.jar:conf org.apache.zookeeper.server.PurgeTxnLog <dataDir><snapDir> -n <count>
第三种,对于上面这个Java类的执行,ZK自己已经写好了脚本,在bin/zkCleanup.sh中,所以直接使用这个脚本也是可以执行清理工作的。
第四种,从3.4.0开始,zookeeper提供了自动清理snapshot和事务日志的功能,通过配置 autopurge.snapRetainCount 和 autopurge.purgeInterval 这两个参数能够实现定时清理了。这两个参数都是在zoo.cfg中配置的:
autopurge.purgeInterval 这个参数指定了清理频率,单位是小时,需要填写一个1或更大的整数,默认是0,表示不开启自己清理功能。
autopurge.snapRetainCount 这个参数和上面的参数搭配使用,这个参数指定了需要保留的文件数目。默认是保留3个。
ZooKeeper有两种日志、一种快照。日志分为事务日志和ZooKeeper运行时的系统日志。
1.事务日志和快照
ZooKeeper集群中的每个服务器节点每次接收到写操作请求时,都会先将这次请求发送给leader,leader将这次写操作转换为带有状态的事务,然后leader会对这次写操作广播出去以便进行协调。当协调通过(大多数节点允许这次写)后,leader通知所有的服务器节点,让它们将这次写操作应用到内存数据库中,并将其记录到事务日志中。
当事务日志记录的次数达到一定数量后(默认10W次),就会将内存数据库序列化一次,使其持久化保存到磁盘上,序列化后的文件称为"快照文件"。每次拍快照都会生成新的事务日志。
有了事务日志和快照,就可以让任意节点恢复到任意时间点(只要没有清理事务日志和快照)。
1.1 事务日志和快照相关的配置项
-
dataDir
:
ZooKeeper的数据目录,主要目的是存储内存数据库序列化后的快照路径。如果没有配置事务日志(即dataLogDir配置项)的路径,那么ZooKeeper的事务日志也存放在数据目录中。 -
dataLogDir
:
指定事务日志的存放目录。事务日志对ZooKeeper的影响非常大,强烈建议事务日志目录和数据目录分开,不要将事务日志记录在数据目录(主要用来存放内存数据库快照)下。 -
preAllocSize
:
为事务日志预先开辟磁盘空间。默认是64M,意味着每个事务日志大小就是64M(可以去事务日志目录中看一下,每个事务日志只要被创建出来,就是64M)。如果ZooKeeper产生快照频率较大,可以考虑减小这个参数,因为每次快照后都会切换到新的事务日志,但前面的64M根本就没写完。(见snapCount配置项) -
snapCount
:
ZooKeeper使用事务日志和快照来持久化每个事务(注意是日志先写)。该配置项指定ZooKeeper在将内存数据库序列化为快照之前,需要先写多少次事务日志。也就是说,每写几次事务日志,就快照一次。默认值为100000。为了防止所有的ZooKeeper服务器节点同时生成快照(一般情况下,所有实例的配置文件是完全相同的),当某节点的先写事务数量在(snapCount/2+1,snapCount)范围内时(挑选一个随机值),这个值就是该节点拍快照的时机。 -
autopurge.snapRetainCount
:
该配置项指定开启了ZooKeeper的自动清理功能后(见下一个配置项),每次自动清理时要保留的版本数量。默认值为3,最小值也为3。它表示在自动清理时,会保留最近3个快照以及这3个快照对应的事务日志。其它的所有快照和日志都清理。 -
autopurge.purgeInterval
:
指定触发自动清理功能的时间间隔,单位为小时,值为大于或等于1的整数,默认值为0,表示不开启自动清理功能。
1.2 事务日志和快照的命名规则
在ZooKeeper集群启动后,当第一个客户端连接到某个服务器节点时,会创建一个会话,这个会话也是事务,于是创建第一个事务日志,一般名为log.100000001
,这里的100000001是这次会话的事务id(zxid)。之后的事务都将写入到这个文件中,直到拍下一个快照。
如果是事务ZXID5触发的拍快照,那么快照名就是snapshot.ZXID5,拍完后,下一个事务的ID就是ZXID6,于是新的事务日志名为log.ZXID6。
1.3 查看事务日志
事务日志是一个二进制文件,无法直接查看。好在ZooKeeper提供了一个LogFormatter工具类。
假设ZooKeeper安装目录为/usr/local/zookeeper,那么可以通过下面的方法来查看事务日志log.100000001中的内容。
java -cp /usr/local/zookeeper/zookeeper-3.4.12.jar:/usr/local/zookeeper/lib/slf4j-api-1.7.25.jar org.apache.zookeeper.server.LogFormatter /usr/local/zookeeper/data/version-2/log.100000001
以下是一个事务日志的内容示例。
1.4 自动清理功能
从ZooKeeper 3.4.0开始,ZooKeeper提供了自动清理事务日志和快照的功能,见事务日志和快照相关的配置项。
此外,还提供了一个脚本zkCleanup.sh,它也用来清理事务日志和快照。但比较少用。
有时也会写定时任务脚本,来删除定时、定点的事务日志和快照数据。
2.ZooKeeper系统的系统日志
ZooKeeper使用log4j(log for java)来记录系统日志。默认情况下,系统日志文件为ZooKeeper安装目录下的zookeeper.out,这是由log4j的配置文件决定的。(实际上,zkEnv.sh和zkServer.sh中也设置了日志的路径,见下文)。
ZooKeeper使用的log4j的配置文件为$ZOOKEEPER_HOME/conf/log4j.properties
。
-
[root@s1 zk]# cat conf/log4j.properties
-
# Define some default values that can be overridden by system properties
-
zookeeper.root.logger=INFO, CONSOLE
-
zookeeper.console.threshold=INFO
-
zookeeper.log.dir=. # 日志目录
-
zookeeper.log.file=zookeeper.log # 日志文件名称
-
zookeeper.log.threshold=DEBUG
-
zookeeper.tracelog.dir=.
-
zookeeper.tracelog.file=zookeeper_trace.log
-
.....省略.......
log4j.properties中没有指定zookeeper.out啊?但为什么会输出到zookeeper.out中呢?这是因为zkServer.sh中指定了这个文件。以下是zkServer.sh中和zookeeper.out相关的内容:
-
.........省略.............
-
_ZOO_DAEMON_OUT="$ZOO_LOG_DIR/zookeeper.out"
-
case $1 in
-
start)
-
echo -n "Starting zookeeper ... "
-
.........省略.............
-
nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
-
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
-
.........省略.............
可以看到,在zkServer.sh的start选项中,使用nohup启动ZooKeeper,并将日志输出到"$ZOO_LOG_DIR/zookeeper.out"中。
一般来说,没有特殊需求,没必要去改log4j日志配置。要改的话,记得把log4j.properties和zkEnv.sh和zkServer.sh中相关的内容都修改掉。