zookeeper-入门实战

zookeeper工作原理

Zookeeper 的核心是广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播 模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后, 恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。为了保证事务的顺序一致性,zookeeper采用了递增的事务id号 (zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用 来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递 增计数。

每个Server在工作过程中有三种状态:

  • LOOKING:当前Server不知道leader是谁,正在搜寻。
  • LEADING:当前Server即为选举出来的leader。
  • FOLLOWING:leader已经选举出来,当前Server与之同步。

zookeeper快速安装

zookeeper配置文件解释

tickTime:CS通信心跳数
Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。tickTime以毫秒为单位。

1
tickTime=2000

initLimit:LF初始通信时限
集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量)。

1
initLimit=5

syncLimit:LF同步通信时限
集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量)。

1
syncLimit=2

dataDir:数据文件目录
Zookeeper保存数据的目录,默认情况下,Zookeeper将写数据的日志文件也保存在这个目录里。

1
dataDir=/data/zk

dataLogDir:日志文件目录
Zookeeper保存日志文件的目录。

1
dataLogDir=/var/log/zookeeper/logs

clientPort:客户端连接端口
客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。

1
clientPort=2181

服务器名称与地址:集群信息(服务器编号,服务器地址,LF通信端口,选举端口)
这个配置项的书写格式比较特殊,规则如下:

1
server.N=YYY:A:B

其中N表示服务器编号,YYY表示服务器的IP地址,A为LF通信端口,表示该服务器与集群中的leader交换的信息的端口。B为选举端口,表示选举新leader时服务器间相互通信的端口(当leader挂掉时,其余服务器会相互通信,选择出新的leader)。一般来说,集群中每个服务器的A端口都是一样,每个服务器的B端口也是一样。但是当所采用的为伪集群时,IP地址都一样,只能时A端口和B端口不一样。

正常集群的例子:

1
2
3
server.1=192.168.56.11:2181:2182
server.2=192.168.56.12:2181:2182
server.3=192.168.56.13:2181:2182

伪集群的例子:

1
2
3
server.1=192.168.56.11:2181:3181
server.2=192.168.56.11:2182:3182
server.3=192.168.56.11:2183:3183

单实例安装

安装zookeeper服务

1
2
3
4
5
6
7
cd /usr/local/src/
tar -zxf zookeeper-3.4.7.tar.gz
mv zookeeper-3.4.7 /usr/local/
ln -s /usr/loacl/zookeeper-3.4.7 /usr/loca/zookeeper
cd /usr/loca/zookeeper
cd conf/
cp zoo_sample.cfg zoo.cfg

编辑配置文件

1
2
3
4
vim zoo.cfg
tickTime=2000
dataDir=/data/zk
clientPort=2181

启动zookeeper服务

1
/usr/loca/zookeeper/bin/zkServer.sh start

检查服务是否正常启动

1
bin/zkCli.sh -server 127.0.0.1:2181

伪集群配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cd /usr/local/src
wget http://mirrors.cnnic.cn/apache/zookeeper/stable/zookeeper-3.4.6.tar.gz
tar zxf zookeeper-3.4.6.tar.gz
mv zookeeper-3.4.6 /usr/local/
ln -s /usr/local/zookeeper-3.4.6/ /usr/local/zookeeper
cd /usr/local/zookeeper/conf/
mv zoo_sample.cfg zoo.cfg
vim zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zk1
clientPort=2181
server.1=192.168.56.11:3181:4181
server.2=192.168.56.11:3182:4182
server.3=192.168.56.11:3183:4183

创建三个目录用来存放zookeeper数据

1
2
3
4
mkdir /data/{zk1,zk2,zk3} -p
echo "1" >/data/zk1/myid
echo "2" >/data/zk2/myid
echo "3" >/data/zk3/myid

生成三份zookeeper配置文件

1
2
3
cp zoo.cfg zk1.cfg
cp zoo.cfg zk2.cfg
cp zoo.cfg zk3.cfg

修改zk2和zk3的配置,使用对应的数据目录和端口。

1
2
3
4
sed -i 's/zk1/zk2/g' zk2.cfg
sed -i 's/2181/2182/g' zk2.cfg
sed -i 's/zk1/zk3/g' zk3.cfg
sed -i 's/2181/2183/g' zk3.cfg

启动Zookeeper

1
2
3
/usr/local/zookeeper/bin/zkServer.sh start /usr/local/zookeeper/conf/zk1.cfg
/usr/local/zookeeper/bin/zkServer.sh start /usr/local/zookeeper/conf/zk2.cfg
/usr/local/zookeeper/bin/zkServer.sh start /usr/local/zookeeper/conf/zk3.cfg

查看Zookeeper角色

1
2
3
4
5
6
7
8
9
10
11
12
/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk1.cfg
#JMX enabled by default
#Using config: /usr/local/zookeeper/conf/zk1.cfg
#Mode: follower
/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk2.cfg
#JMX enabled by default
#Using config: /usr/local/zookeeper/conf/zk2.cfg
#Mode: `leader`
/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk3.cfg
#JMX enabled by default
#Using config: /usr/local/zookeeper/conf/zk3.cfg
#Mode: follower

连接Zookeeper

1
/usr/local/zookeeper/bin/zkCli.sh -server192.168.56.11:2181

通过上面的例子可以看到,目前zk2是leader,其它两个节点是follower。
本文由于实验环境局限使用的是伪分布式。
生产环境不建议使用。

集群模式

集群模式的配置和伪集群基本一致.
由于集群模式下, 各server部署在不同的机器上, 因此各server的conf/zoo.cfg文件可以完全一样.

下面是一个示例:

1
2
3
4
5
6
7
8
9
tickTime=2000 
initLimit=5 
syncLimit=2 
dataDir=/home/zookeeper/data 
dataLogDir=/home/zookeeper/logs 
clientPort=4180 
server.1=192.168.56.11:3181:4182
server.2=192.168.56.12:3181:4182
server.3=192.168.56.13:3181:4182

示例中部署了3台zookeeper server, 分别部署在192.168.56.11, 192.168.56.12, 1192.168.56.13上. 需要注意的是, 各server的dataDir目录下的myid文件中的数字必须不同,192.168.56.11 server的myid为1, 192.168.56.12 server的myid为2, 192.168.56.13server的myid为3。

zookeeper常用四字命令:

  • echo stat|nc 127.0.0.1 2181 来查看哪个节点被选择作为follower或者leader
  • echo ruok|nc 127.0.0.1 2181 测试是否启动了该Server,若回复imok表示已经启动
  • echo dump| nc 127.0.0.1 2181 ,列出未经处理的会话和临时节点。
  • echo kill | nc 127.0.0.1 2181 ,关掉server
  • echo conf | nc 127.0.0.1 2181 ,输出相关服务配置的详细信息。
  • echo cons | nc 127.0.0.1 2181 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。
  • echo envi |nc 127.0.0.1 2181 ,输出关于服务环境的详细信息(区别于 conf 命令)。
  • echo reqs | nc 127.0.0.1 2181 ,列出未经处理的请求。
  • echo wchs | nc 127.0.0.1 2181 ,列出服务器 watch 的详细信息。
  • echo wchc | nc 127.0.0.1 2181 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个与 watch 相关的会话的列表。
  • echo wchp | nc 127.0.0.1 2181 ,通过路径列出服务器 watch 的详细信息。它输出一个与 session 相关的路径。

zookeeper监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
`vim bin/zkServer.sh`

#修改前
#ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=$JMXLOCALONLY org.apache.zookeeper.server.quorum.QuorumPeerMa
in"

#修改后
ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=192.168.56.22
-Dcom.sun.management.jmxremote.port=9991
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dzookeeper.jmx.log4j.disable=true
org.apache.zookeeper.server.quorum.QuorumPeerMain"

更改完以后重启zookeeper服务器,使用JMX客户端连接服务器: