Zookeeper有两种运行模式:
独立模式(standalone mode):只运行在一台服务器上,适合测试环境。
复制模式(replicated mode):运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble)
复制模式的Zookeeper通过复制来实现高可用性,只要集合体中半数以上的机器处于可用状态,它就能够保证服务继续。这跟Zookeeper的复制策略有关:Zookeeper确保对znode树的每一个修改都会被复制到集合体中超过半数的机器上。
Zookeeper服务有两个角色,一个是leader,负责写服务和数据同步,剩下的是follower,提供读服务,leader失效后会在follower中重新选举新的leader。在整个Zookeeper集群模式下,整个集群是一个整体,在集群中的任何一个Zookeeper节点共享整个集群的服务。
环境:
操作系统:CentOS Linux release 7.3.1611 (Core)
Zookeeper:zookeeper-3.4.12
IP:10.55.2.81-83
Zookeeper下载地址:http://zookeeper.apache.org/releases.html#download
[root@zk-2-82-0001 soft]# tar -xvf zookeeper-3.4.12.tar.gz
[root@zk-2-82-0001 soft]# mv zookeeper-3.4.12 zookeeper
[root@zk-2-82-0001 soft]# mv zookeeper /app
[root@zk-2-82-0001 soft]# cd /app/zookeeper
[root@zk-2-82-0001 zookeeper]# mkdir data
[root@zk-2-82-0001 zookeeper]# mv conf/zoo_sample.cfg conf/zoo.cfg
[root@zk-2-82-0001 zookeeper]# vim conf/zoo.cfg
# The number of milliseconds of each tick
tickTime=2000 //Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,每隔tickTime时间就会发送一个心跳
# The number of ticks that the initial
# synchronization phase can take
initLimit=10 //配置 Zookeeper 接受客户端(此客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已超过initLimit个tickTime长度后 Zookeeper 服务器还没有收到客户端的返回信息,则表明客户端连接失败。总的时间长度就是 initLimit * tickTime 秒。
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5 //配置 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 syncLimit * tickTime 秒
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/app/zookeeper/data //Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里
dataLogDir=/app/zookeeper/logs //若没提供的话则用dataDir。zookeeper的持久化都存储在这两个目录里。dataLogDir里是放到的顺序日志(WAL),指定的目录下有version-2文件夹(下有log.1文件)。而dataDir里放的是内存数据结构的snapshot,便于快速恢复。为了达到性能最大化,一般建议把dataDir和dataLogDir分到不同的磁盘上,以充分利用磁盘顺序写的特性。
# the port at which the clients will connect
clientPort=2181 //Zookeeper服务器监听的端口,以接受客户端的访问请求。
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1=10.55.2.81:2888:3888
server.2=10.55.2.82:2888:3888
server.3=10.55.2.83:2888:3888
// server.n n是一个数字,表示这个是第几号服务器;“=”号后面是对应几号服务器的IP地址,2888是这个服务器与集群中的 Leader 服务器交换信息的端口;3888表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,此端口就是用来执行选举时服务器相互通信的端口。
每个节点的zoo.cfg配置都一样,直接复制过去就可以。
2、添加myid文件
除了修改 zoo.cfg 配置文件,集群模式下还要配置一个文件 myid,这个文件在zoo.cfg里dataDir指定的目录下,这个文件里面就只有一个数字,这个数字和server.n的n保持一致,Zookeeper 启动时会读取这个文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是那个 server。
[root@zk-2-82-0001 zookeeper]# echo "2">data/myid
其他两个节点类似
3、安装jdk
[root@zk-2-82-0001 soft]# rpm -ivh jdk-8u151-linux-x64.rpm
4、启动服务
[root@zk-2-82-0001 zookeeper]# cd bin/
[root@zk-2-82-0001 bin]# ls
README.txt zkCleanup.sh zkCli.cmd zkCli.sh zkEnv.cmd zkEnv.sh zkServer.cmd zkServer.sh zookeeper.out
[root@zk-2-82-0001 bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /app/zookeeper/bin/../conf/zoo.cfg
Error contacting service. It is probably not running. //少于三台不会正常工作,三台都启动次,然后删除pid文件再启动, zookeeper.out里有很多有用的提示
[root@zk-2-82-0001 bin]# rm -rf ../conf/zoo_sample.cfg
[root@zk-2-82-0001 bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /app/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@zk-2-82-0001 bin]#
使用jps -m可以查询进程,Zookeeper的进程为QuorumPeerMain
[root@zk-2-82-0001 bin]# jps -m
1744 WrapperSimpleApp CloudResetPwdUpdateAgent
2528 QuorumPeerMain /app/zookeeper/bin/../conf/zoo.cfg
21745 Jps -m
[root@zk-2-82-0001 bin]#
5、节点状态查看
[root@zk-2-82-0001 bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /app/zookeeper/bin/../conf/zoo.cfg
Mode: leader
[root@zk-2-82-0001 bin]#
[root@zk-2-81 bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /app/zookeeper/bin/../conf/zoo.cfg
Mode: follower
[root@zk-2-81 bin]#
[root@zk-2-82-0002 bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /app/zookeeper/bin/../conf/zoo.cfg
Mode: follower
[root@zk-2-82-0002 bin]#
日志
[root@zk-2-82-0001 bin]# tail -500f zookeeper.out
2018-06-21 15:24:59,618 [myid:] - INFO [main:QuorumPeerConfig@136] - Reading configuration from: /app/zookeeper/bin/../conf/zoo.cfg
2018-06-21 15:24:59,626 [myid:] - INFO [main:QuorumPeer$QuorumServer@184] - Resolved hostname: 10.55.2.81 to address: /10.55.2.81
2018-06-21 15:24:59,626 [myid:] - INFO [main:QuorumPeer$QuorumServer@184] - Resolved hostname: 10.55.2.83 to address: /10.55.2.83
2018-06-21 15:24:59,626 [myid:] - INFO [main:QuorumPeer$QuorumServer@184] - Resolved hostname: 10.55.2.82 to address: /10.55.2.82
2018-06-21 15:24:59,626 [myid:] - INFO [main:QuorumPeerConfig@398] - Defaulting to majority quorums
2018-06-21 15:24:59,628 [myid:2] - INFO [main:DatadirCleanupManager@78] - autopurge.snapRetainCount set to 3
2018-06-21 15:24:59,628 [myid:2] - INFO [main:DatadirCleanupManager@79] - autopurge.purgeInterval set to 0
2018-06-21 15:24:59,628 [myid:2] - INFO [main:DatadirCleanupManager@101] - Purge task is not scheduled.
2018-06-21 15:24:59,635 [myid:2] - INFO [main:QuorumPeerMain@130] - Starting quorum peer
2018-06-21 15:24:59,639 [myid:2] - INFO [main:ServerCnxnFactory@117] - Using org.apache.zookeeper.server.NIOServerCnxnFactory as server connection factory
2018-06-21 15:24:59,642 [myid:2] - INFO [main:NIOServerCnxnFactory@89] - binding to port 0.0.0.0/0.0.0.0:2181
2018-06-21 15:24:59,646 [myid:2] - INFO [main:QuorumPeer@1158] - tickTime set to 2000
2018-06-21 15:24:59,646 [myid:2] - INFO [main:QuorumPeer@1204] - initLimit set to 10
6、ZooKeeper访问
[root@zk-2-82-0001 bin]# ./zkCli.sh -server 10.55.2.82:2181 //连接loader节点,写入数据验证集群
Connecting to 10.55.2.82:2181
2018-06-21 18:15:33,887 [myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.12-e5259e437540f349646870ea94dc2658c4e44b3b, built on 03/27/2018 03:55 GMT
......
WATCHER::
WatchedEvent state:SyncConnected type:None path:null //回车
[zk: 10.55.2.82:2181(CONNECTED) 0] ls / //显示根目录下、文件,用ls /命令查看目录情况,发现只有一个zookeeper目录。
[zookeeper]
[zk: 10.55.2.82:2181(CONNECTED) 0] help //运行帮助命令
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit
getAcl path
close
connect host:port
[zk: 10.55.2.82(CONNECTED) 0] ls2 / //显示根目录下、文件,查看当前节点数据并能看到更新次数等数据
[zookeeper, 20180621]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x100000004
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
[zk: 10.55.2.82:2181(CONNECTED) 1] create /20180621 "201806211950" //创建文件并设置初始内容,创建一个新的 znode节点“ 20180621 ”以及与它关联的字符串
Created /20180621
[zk: 10.55.2.82:2181(CONNECTED) 2] ls /
[zookeeper, 20180621]
[zk: 10.55.2.82:2181(CONNECTED) 3] get /20180621 //获取文件内容,确认 znode 是否包含我们所创建的字符串
201806211950
cZxid = 0x100000004
ctime = Thu Jun 21 19:50:05 CST 2018
mZxid = 0x100000004
mtime = Thu Jun 21 19:50:05 CST 2018
pZxid = 0x100000004
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 0
[zk: 10.55.2.82(CONNECTED) 3] set /20180621 "justin 51cto" //修改文件内容,对 20180621 所关联的字符串进行设置
cZxid = 0x100000004
ctime = Thu Jun 21 19:50:05 CST 2018
mZxid = 0x10000000b
mtime = Thu Jun 21 20:23:43 CST 2018
pZxid = 0x100000004
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 0
[zk: 10.55.2.82(CONNECTED) 4] get /20180621
justin 51cto
cZxid = 0x100000004
ctime = Thu Jun 21 19:50:05 CST 2018
mZxid = 0x10000000b
mtime = Thu Jun 21 20:23:43 CST 2018
pZxid = 0x100000004
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 0
[zk: 10.55.2.82(CONNECTED) 5] delete /20180621 //修改文件内容,将刚才创建的 znode 删除;如果要 删除目录(即使非空)使用:rmr 目录
[zk: 10.55.2.82:2181(CONNECTED) 4] quit
Quitting...
2018-06-21 19:50:28,534 [myid:] - INFO [main:ZooKeeper@687] - Session: 0x200004654110000 closed
2018-06-21 19:50:28,535 [myid:] - INFO [main-EventThread:ClientCnxn$EventThread@521] - EventThread shut down for session: 0x200004654110000
[root@zk-2-82-0001 bin]#
此时,登陆到其他节点也可以看到。在data目录里,
snapshot.0:就是我们存放数据在内存中的快照,zookeeper服务刚启动时需要用它来恢复数据
log.100000001:日志文件,默认存放在数据目录中。
6、ssh远程开启Zookeeper服务
[root@zk-2-82-0001 bin]# ssh 10.55.2.81 "source /etc/profile;/app/zookeeper/bin/zkServer.sh status"
这样我们就可以通过脚本来同时管理3个节点了
7、四字命令
通过四字命令更方便地获取服务端信息, 四字命令的用法:echo 四字命令|netcat localhost 2181 ,常用的四字:
conf:输出Zookeeper服务器配置的详细信息
cons:输出所有连接到服务器的客户端的完全的连接/会话的详细信息。包括“接收/发送”的包数量、会话ID、操作延迟、最后的操作执行等
dump:输出未经处理的会话和临时节点
envi:输出关于服务器运行环境的详细信息
reqs:输出未经处理的请求
ruok:测试服务是否处于正确状态。若是则会返回“imok”,否则不做任何反应
stat:输出关于性能和连接的客户端的列表。(通过此命令也可查看节点是leader还是follower)
wchs:输出服务器watch的详细信息
wchc:通过session列出服务器watch的详细信息,它的输出是一个与watch相关的会话的列表
wchp:通过路径列出服务器watch的详细信息,它输出一个与session相关的路径
mntr:输出一些Zookeeper运行时信息,通过对这些返回结果的解析可以达到监控效果
netcat下载地址:http://sourceforge.net/projects/netcat/files/netcat/
[root@zk-2-82-0001 soft]# echo conf|netcat 10.55.2.81 2181
数据及日志维护
Zookeeper的数据文件存放在配置中指定的dataDir中,每个数据文件名都以snapshot开头,每个数据文件为zookeeper某个时刻数据全量快照。在zookeeper中,对数据的更新操作,包括创建节点、更新节点内容、删除节点都会记录事务日志;客户端对ZK的更新操作都是永久的,不可回退的。为做到这点,ZK会将每次更新操作以事务日志的形式写入磁盘,写入成功后才会给予客户端响应。zookeeper在完成若干次事务日志(snapCount)后会生成一次快照,把当前zk中的所有节点的状态以文件的形式dump到硬盘中,生成一个snapshot文件。这里的事务次数是可以配置,默认是100000个。
zookeeper服务器会产生三类日志:事务日志、快照日志和log4j日志。
事务日志
事务日志指zookeeper系统在正常运行过程中,针对所有的更新操作,在返回客户端“更新成功”的响应前,zookeeper会保证已经将本次更新操作的事务日志已经写到磁盘上,只有这样,整个更新操作才会生效。
在dataLogDir指定的目录下存在一个文件夹version-2,该文件夹中保存着事物日志文件:
[root@zk-2-82-0001 data]# cd version-2/
[root@zk-2-82-0001 version-2]# ls
acceptedEpoch currentEpoch log.100000001
[root@zk-2-82-0001 version-2]#
日志文件的命名规则为log.,表示写入该日志的第一个事务的ID,十六进制表示。
事务日志可视化
zookeeper的事务日志为二进制文件,不能通过vim等工具直接访问。可以通过zookeeper自带的jar包读取事务日志文件。执行如下命令:
[root@zk-2-82-0001 zookeeper]# java -classpath .:lib/slf4j-api-1.7.25.jar:zookeeper-3.4.12.jar org.apache.zookeeper.server.LogFormatter data/version-2/log.100000001
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
6/21/18 6:15:33 PM CST session 0x1000045eba30000 cxid 0x0 zxid 0x100000001 createSession 30000
6/21/18 6:59:45 PM CST session 0x1000045eba30000 cxid 0x2 zxid 0x100000002 closeSession null
6/21/18 7:47:53 PM CST session 0x200004654110000 cxid 0x0 zxid 0x100000003 createSession 30000
6/21/18 7:50:05 PM CST session 0x200004654110000 cxid 0x1 zxid 0x100000004 create ‘/20180621,#323031383036323131393530,v{s{31,s{‘world,‘anyone}}},F,1
6/21/18 7:50:28 PM CST session 0x200004654110000 cxid 0x5 zxid 0x100000005 closeSession null
6/21/18 7:51:01 PM CST session 0x1000045eba30001 cxid 0x0 zxid 0x100000006 createSession 30000
6/21/18 7:53:30 PM CST session 0x1000045eba30001 cxid 0x4 zxid 0x100000007 closeSession null
6/21/18 8:18:55 PM CST session 0x200004654110001 cxid 0x0 zxid 0x100000008 createSession 30000
6/21/18 8:21:15 PM CST session 0x200004654110002 cxid 0x0 zxid 0x100000009 createSession 30000
6/21/18 8:21:36 PM CST session 0x200004654110001 cxid 0x0 zxid 0x10000000a closeSession null
6/21/18 8:23:43 PM CST session 0x200004654110002 cxid 0x6 zxid 0x10000000b setData ‘/20180621,#6a757374696e20353163746f,1
6/21/18 8:25:09 PM CST session 0x200004654110002 cxid 0xa zxid 0x10000000c delete ‘/20180621
6/21/18 8:34:46 PM CST session 0x200004654110002 cxid 0xb zxid 0x10000000d closeSession null
EOF reached after 13 txns.
[root@zk-2-82-0001 zookeeper]#
快照日志
zookeeper的数据在内存中是以树形结构进行存储的,而快照就是每隔一段时间就会把整个DataTree的数据序列化后存储在磁盘中,这就是zookeeper的快照文件。在dataDir指定的目录下存在一个文件夹version-2,该文件夹中保存着快照日志文件:
[root@zk-2-82-0002 version-2]# ls
acceptedEpoch currentEpoch log.100000001 snapshot.100000000
[root@zk-2-82-0002 version-2]#
zookeeper快照文件的命名规则为snapshot.,其中表示zookeeper触发快照的那个瞬间,提交的最后一个事务的ID。
日志清理
在zookeeper 3.4.0以后,zookeeper提供了自动清理snapshot和事务日志功能,通过配置zoo.cfg下的autopurge.snapRetainCount和autopurge.purgeInterval这两个参数实现日志文件的定时清理。
autopurge.snapRetainCount这个参数指定了需要保留的文件数目,默认保留3个;
autopurge.purgeInterval这个参数指定了清理频率,单位是小时,需要填写一个1或者更大的数据,0表示不开启自动清理功能。
[root@zk-2-82-0001 bin]# grep -in "autopurge" ../conf/zoo.cfg
21:# administrator guide before turning on autopurge.
26:#autopurge.snapRetainCount=3
29:#autopurge.purgeInterval=1
[root@zk-2-82-0001 bin]#
原文:http://blog.51cto.com/ityunwei2017/2131509