前言

相信大家对 ZooKeeper 应该不算陌生,ZooKeeper 的使用和 ZooKeeper 集群的搭建并不复杂,这里分享自己看到的一些好文章以及使用 Ansible 快速部署和手动部署 ZooKeeper 的经验分享。

ZooKeeper 分布式环境的协调利器

更新历史

2018 年 09 月 27 日 - 初稿

阅读原文 - https://wsgzao.github.io/post/zookeeper/

扩展阅读

ZooKeeper - https://zookeeper.apache.org/


ZooKeeper 简介

ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications. Each time they are implemented there is a lot of work that goes into fixing the bugs and race conditions that are inevitable. Because of the difficulty of implementing these kinds of services, applications initially usually skimp on them ,which make them brittle in the presence of change and difficult to manage. Even when done correctly, different implementations of these services lead to management complexity when the applications are deployed.

ZooKeeper 是一个开源的为分布式应用提供分布式协调的服务。它公开了一组简单的原语,分布式应用程序可以基于这些原语实现更高级别的服务,包括同步、维护配置、组和命名。它的设计易于编程,它使用一个遵循文件系统中常见的目录树结构的数据模型。它在 Java 环境中运行,对 Java 和 C 都有绑定。
协调服务是出了名的难。它们特别容易出错,如竞态条件和死锁。ZooKeeper 背后的动机是让分布式应用从零开始实现一站式协调服务。

翻译:ZooKeeper OverView
https://www.cnblogs.com/f-ck-need-u/p/9231153.html

可能是全网把 ZooKeeper 概念讲的最清楚的一篇文章
https://github.com/Snailclimb/JavaGuide/blob/master/docs/system-design/framework/ZooKeeper.md

ZooKeeper 相关概念总结
ZooKeeper 数据模型和常见命令

jdk

install jdk by ansible

https://galaxy.ansible.com/geerlingguy/java

1
2
3
4
5
6
7
8
9
10
11
12
# download
ansible-galaxy install geerlingguy.java
# create yaml file and config java version
vi install_jdk.yml

---
- hosts: all
roles:
- role: geerlingguy.java
when: "ansible_os_family =='RedHat'"
java_packages:
- java-1.8.0-openjdk

install jdk manually

http://www.oracle.com/technetwork/java/javase/downloads/index.html

1
2
3
4
5
6
7
8
9
10
11
12
# yum
yum install java-1.8.0-openjdk
# rpm
yum localinstall -y jdk-8u181-linux-x64.rpm
# set env
vi /etc/profile

export JAVA_HOME=/usr/java/jdk1.8.0_181
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib 
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin 

source /etc/profile

zookeeper

install zookeeper by ansible

ansible-zookeeper

zookeeper stand-alone

1
2
3
4
5
6
7
8
9
10
11
12
13
# install jdk
yum -y install java-1.8.0-openjdk
# download and install zookeeper
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
tar -zxvf zookeeper-3.4.14.tar.gz -C /opt
ln -s /opt/zookeeper-3.4.14 /opt/zookeeper
cd /opt/zookeeper
# create zoo.cfg
cd /opt/zookeeper/conf
cp zoo_sample.cfg zoo.cfg
# start zookeeper
/opt/zookeeper/bin/zkServer.sh start
/opt/zookeeper/bin/zkCli.sh -server 127.0.0.1:2181

install zookeeper manually

https://zookeeper.apache.org/releases.html#download
https://archive.apache.org/dist/zookeeper/stable/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# install jdk
yum -y install java-1.8.0-openjdk
# download and install zookeeper
tar -zxvf zookeeper-3.4.14.tar.gz —C /opt
ln -s /opt/zookeeper-3.4.14 /opt/zookeeper
cd /opt/zookeeper
# create zoo.cfg
cd /opt/zookeeper/conf
cp zoo_sample.cfg zoo.cfg
vi zoo.cfg

tickTime=2000
dataDir=/var/lib/zookeeper
dataLogDir=/var/log/zookeeper
clientPort=2181
initLimit=5
syncLimit=2

server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

# create directory
mkdir /var/lib/zookeeper
mkdir /var/log/zookeeper
# create myid file in different zookeeper
cd /var/lib/zookeeper/

echo 1 > /var/lib/zookeeper/myid
echo 2 > /var/lib/zookeeper/myid
echo 3 > /var/lib/zookeeper/myid

# live
cat << EOF > /opt/zookeeper/conf/zoo.cfg
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/data/zookeeper/data
dataLogDir=/var/log/zookeeper
clientPort=2181
server.1=192.168.188.120:2888:3888
server.2=192.168.188.121:2888:3888
server.3=192.168.188.122:2888:3888
EOF

# autostart
echo '/opt/zookeeper/bin/zkServer.sh start' >> /etc/rc.local

# start
cd /usr/local/zookeeper/bin
./zkServer.sh start
# check
./zkServer.sh status
# create znode
./zkCli.sh -server 127.0.0.1:2181
create /codis codis
ls /
[zookeeper, codis]

Zookeeper Configuration

Platform: RHEL / CentOS 7
Java: Oracle JDK

Variables

1
2
3
4
5
6
7
8
9
10
11
12
zookeeper_version: 3.4.14
zookeeper_group: zookeeper
zookeeper_user: zookeeper
zookeeper_dir: /opt/zookeeper-{{zookeeper_version}} # or /opt/zookeeper
zookeeper_conf_dir: {{zookeeper_dir}} # or /etc/zookeeper
zookeeper_tarball_dir: /opt/src
data_dir: /var/lib/zookeeper
log_dir: /var/log/zookeeper
zookeeper_client_port: 2181
zookeeper_id: 1
zookeeper_leader_port: 2888
zookeeper_election_port: 3888

Default Ports

Port Description
2181 Client connection port
2888 Quorum port for clustering
3888 Leader election port for clustering

conf/zoo.cfg

1
2
3
4
5
6
7
8
9
tickTime=2000
dataDir=/var/lib/zookeeper
dataLogDir=/var/log/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

tickTime
the basic time unit in milliseconds used by ZooKeeper. It is used to do heartbeats and the minimum session timeout will be twice the tickTime.

dataDir
the location to store the in-memory database snapshots and, unless specified otherwise, the transaction log of updates to the database.

clientPort
the port to listen for client connections

initLimit
is timeouts ZooKeeper uses to limit the length of time the ZooKeeper servers in quorum have to connect to a leader.

syncLimit
limits how far out of date a server can be from a leader.

In this example, the timeout for initLimit is 5 ticks at 2000 milleseconds a tick, or 10 seconds.

zookeeper test

1
2
3
4
5
6
7
8
9
10
11
12
13
# 连接到 192.168.1.3
ganlixins-MacBook-Pro:~ ganlixin$ /usr/local/zookeeper/bin/zkCli.sh -server 192.168.1.3:2181
[zk: 192.168.1.3:2181(CONNECTED) 0] create /abc 123
Created /abc
[zk: 192.168.1.3:2181(CONNECTED) 1] create /xyz 666
Created /xyz
[zk: 192.168.1.3:2181(CONNECTED) 2] quit
Quitting...

# 连接到 192.168.1.4
ganlixins-MacBook-Pro:~ ganlixin$ /usr/local/zookeeper/bin/zkCli.sh -server 192.168.1.4:2181
[zk: 192.168.1.4:2181(CONNECTED) 0] ls /
[xyz, abc, zookeeper]

zookeeper 配置参数详解

conf 中 zoo.cfg 配置文件参数详细说明表

参数名 说明
clientPort 客户端连接 server 的端口,即对外服务端口,一般设置为 2181 吧。
dataDir 存储快照文件 snapshot 的目录。默认情况下,事务日志也会存储在这里。建议同时配置参数 dataLogDir, 事务日志的写性能直接影响 zk 性能。
tickTime ZK 中的一个时间单元。ZK 中所有时间都是以这个时间单元为基础,进行整数倍配置的。例如,session 的最小超时时间是 2*tickTime。
dataLogDir 事务日志输出目录。尽量给事务日志的输出配置单独的磁盘或是挂载点,这将极大的提升 ZK 性能。 (No Java system property)
globalOutstandingLimit 最大请求堆积数。默认是 1000。ZK 运行的时候, 尽管 server 已经没有空闲来处理更多的客户端请求了,但是还是允许客户端将请求提交到服务器上来,以提高吞吐性能。当然,为了防止 Server 内存溢出,这个请求堆积数还是需要限制下的。 (Java system property:zookeeper.globalOutstandingLimit. )
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,可以尝试一下:http://rdc.taobao.com/team/jm/archives/1334(No Java system property)
clientPortAddress 对于多网卡的机器,可以为每个 IP 指定不同的监听端口。默认情况是所有 IP 都监听 clientPort 指定的端口。 New in 3.3.0
minSessionTimeoutmaxSessionTimeoutSession 超时时间限制,如果客户端设置的超时时间不在这个范围,那么会被强制设置为最大或最小时间。默认的 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)
initLimitFollowe r 在启动过程中,会从 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 选举过程中投票通信。 (No Java system property)
group.x=nnnnn[:nnnnn]weight.x=nnnnn 对机器分组和权重设置,可以 参见这里(No Java system property)
cnxTimeoutLeader 选举过程中,打开一次连接的超时时间,默认是 5s。(Java system property: zookeeper. cnxTimeout)
zookeeper.DigestAuthenticationProvider.superDigestZK 权限设置相关,具体参见 《 使用 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 )

zookeeper 常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[zk: 127.0.0.1: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

参考资料

ZooKeeper 系列文章
https://www.cnblogs.com/f-ck-need-u/p/7576137.html#zk

ZooKeeper 系列(1):安装搭建 ZooKeeper 环境
https://www.cnblogs.com/f-ck-need-u/p/9235308.html

Administrator’s Guide - a guide for system administrators and anyone else who might deploy ZooKeeper
https://zookeeper.apache.org/doc/current/zookeeperAdmin.html

文章目录
  1. 1. 前言
  2. 2. 更新历史
  3. 3. ZooKeeper 简介
  4. 4. jdk
    1. 4.1. install jdk by ansible
    2. 4.2. install jdk manually
  5. 5. zookeeper
    1. 5.1. install zookeeper by ansible
    2. 5.2. zookeeper stand-alone
    3. 5.3. install zookeeper manually
  6. 6. Zookeeper Configuration
  7. 7. zookeeper test
  8. 8. zookeeper 配置参数详解
  9. 9. zookeeper 常用命令
  10. 10. 参考资料