Luckylau's Blog

Zookeeper的原理(1)

​ Apache Zookeeper是由Apache Hadoop的子项目发展而来,于2010年11月正式成为Apache顶级项目。Zookeeper为分布式应用提供高效且可靠的分布式协调服务,提供了统一命名服务、配置管理、分布式锁等分布式的基础服务。Zookeeper并没有直接采用Paxos算法,而是采用了一种被称为ZAB(Zookeeper Atomic Broadcast)的一致性协议。

什么是Zookeeper

​ Zookeeper是一个开源的分布式协调服务,由Yahoo创建,是Google Chubby的开源实现。Zookeeper将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。

Zookeeper可以保证如下分布式一致性特性:

顺序一致性:从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到Zookeeper中;

原子性:所有事务的请求结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么在整个集群中所有机器上都成功应用了某一个事务,要么都没有应用,没有中间状态;

单一视图:无论客户端连接的是哪个Zookeeper服务器,其看到的服务端数据模型都是一致的;

实时性:通常人们看到实时性的第一反应是,一旦一个事务被成功应用,那么客户端能够立即从服务端上读取到这个事务变更后的最新数据状态。这里需要注意的是,Zookeeper仅仅保证在一定的时间内,客户端最终一定能够从服务端上读到最终的数据状态;

可靠性:一旦服务端成功应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更会被一直保留下来,除非有另一个事务又对其进行了变更;

Zookeeper能做什么

​ 基于Zookeeper实现例如,数据发布/订阅负载均衡命名服务协调通知集群管理Master选举分布式锁分布式队列等功能 ,可以参考我的Zookpeer-Learning项目

​ Zookeeper在大型分布式系统中有重要应用,比如Hadoop, HBase, Kafka;在国内阿里,比如消息中间件Metamorphosis, RPC服务框架Dubbo, 基于MySQL Binlog的增量订阅和消费组件Cannal, 分布式数据库同步系统Otter, 轻量级分布式通用搜索平台终搜,实时计算引擎JStorm。

Zookeeper的安装使用

在这里以单点部署为例子,我用的root权限,记得环境已经安装了java。

1
yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel

首先你可以购买一台腾讯云虚拟机(Centos7),然后登录官网,复制链接, 下载3.4.9版本。

1
wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.9/zookeeper-3.4.9.tar.gz

解压zookeeper-3.4.9.tar.gz

1
tar -zxvf zookeeper-3.4.9.tar.gz

在/home/luckylau/zookeeper-3.4.9 目录下创建以下目录:

1
2
3
cd /home/luckylau/zookeeper-3.4.9/
mkdir data
mkdir logs

将 zookeeper-3.4.9/conf 目录下的 zoo_sample.cfg 文件拷贝一份,命名为为
zoo.cf

1
cp zoo_sample.cfg zoo.cfg

修改 zoo.cfg 配置文件

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
The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/home/luckylau/zookeeper-3.4.9/data
# the port at which the clients will connect
clientPort=2181
# 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
#2888 端口号是 zookeeper 服务之间通信的端口。
#3888 是 zookeeper 与其他应用程序通信的端口。
server.1=119.27.162.9:2888:3888

更改日志文件位置

1
2
3
4
5
vim /home/luckylau/zookeeper-3.4.9/bin/zkEnv.sh
if [ "x${ZOO_LOG_DIR}" = "x" ]
then
ZOO_LOG_DIR="/home/luckylau/zookeeper-3.4.9/logs"
fi

在 dataDir=/home/luckylau/zookeeper-3.4.9/data 下创建 myid 文件

1
2
vi myid
1

暴露zookeeper配置

1
2
3
4
5
vim .bash_profile
# zookeeper env
export ZOOKEEPER_HOME=/home/luckylau/zookeeper-3.4.9
export PATH=$ZOOKEEPER_HOME/bin:$PATH
source .bash_profile

启动并测试 zookeeper

1
2
3
zkServer.sh start
jps
zkServer.sh status

基本配置参数

参数名 说明
clientPort 该参数无默认值,必须配置,不支持系统属性方式配置。参数clientPort用于配置当前服务器对外的服务端口,客户端会通过该端口和ZooKeeper服务器创建连接,一般设置为2181。
dataDir 该参数无默认值,必须配置,不支持系统属性方式配置。参数dataDir用于配置ZooKeeper服务器存储快照文件的目录。默认情况下,如果没有配置参数dataLogDir,那么事务日志也会存储在这个目录中。考虑到事务日志的写性能直接影响ZooKeeper整体的服务能力,因此建议同时通过参数dataLogDir来配置ZooKeeper事务日志的存储目录。
tickTime 该参数有默认值:3000,单位是毫秒(ms),可以不配置,不支持系统属性方式配置。参数tickTime用于配置ZooKeeper中最小时间单元的长度,很多运行时的时间间隔都是使用tickTime的倍数来表示的。例如,ZooKeeper中会话的最小超时时间默认是2*tickTime。
参数名 说明
dataLogDir 该参数有默认值:dataDir,可以不配置,不支持系统属性方式配置。参数dataLogDir用于配置ZooKeeper服务器存储事务日志文件的目录。默认情况下,ZooKeeper会将事务日志文件和快照数据存储在同一个目录中,应尽量将这两者的目录区分开来。另外,如果条件允许,可以将事务日志的存储配置在一个单独的磁盘上。事务日志记录对于磁盘的性能要求非常高,为了保证事务的一致性,ZooKeeper在返回客户端事务请求响应之前,必须将本次请求对应的事务日志写入到磁盘中。因此,事务日志写入的性能直接决定了ZooKeeper在处理事务请求时的吞吐。针对同一块磁盘的其他并发读写操作(例如ZooKeeper运行时输出和操作系统自身的读写等),尤其是数据快照操作,会极大地影响事务日志的写性能。因此尽量给事务日志的输出配置一个单独的磁盘或是挂载点,将极大地提升ZooKeeper的整体性能。
initLimit 该参数有默认值:10,即表示是参数tickTime值的10倍,必须配置,且需要配置一个正参数,不支持系统属性方式配置。该参数用于配置Leader服务器等待Follower启动,并完成数据同步的时间。Follower服务器在启动过程中,会与Leader建立连接并完成对数据的同步,从而确定自己对外提供服务的起始状态。Leader服务器允许Follower在initLimit时间内完成这个工作。通常情况下,运维人员不用太在意这个参数的配置,使用其默认值即可。但如果随着ZooKeeper集群管理的数据量增大,Follower服务器在启动的时候,从Leader上进行同步数据的时间也会相应变长,于是无法在较短的时间完成数据同步。因此,在这种情况下,有必要适当调大这个参数。
syncLimit 该参数有默认值:5,即表示是参数tickTime值的5倍,必须配置,且需要配置一个正整数,不支持系统属性方式配置。该参数用于配置Leader服务器和Follower之间进行心跳检测的最大延时时间。在ZooKeeper集群运行过程中,Leader服务器会与所有的Follower进行心跳检测来确定该服务器是否存活。如果Leader服务器在syncLimit时间内无法获取到Follower的心跳检测响应,那么Leader就会认为该Follower已经脱离了和自己的同步。通常情况下,运维人员使用该参数的默认值即可,但如果部署ZooKeeper集群的网络环境质量较低(例如网络延时较大或丢包严重),那么可以适当调大这个参数。
snapCount 该参数有默认值:100000,可以不配置,仅支持系统属性方式配置:zookeeper.snapCount。参数snapCount用于配置相邻两次数据快照之间的事务操作次数,即ZooKeeper会在snapCount次事务操作之后进行一次数据快照。
preAllocSize 该参数有默认值:65536,单位是KB,即64KB,可以不配置,仅支持系统属性方式配置:zookeeper.preAllocSize。参数preAllocSize用于配置ZooKeeper事务日志文件预分配的磁盘空间大小。通常情况下,我们使用ZooKeeper的默认配置65536KB即可,但是如果我们将参数snapCount设置得比默认值更小或更大,那么preAllocSize参数也随之做出变更。举个例子来说:如果我们将snapCount的值设置为500,同时预估每次事务操作的数据量大小至多1KB,那么参数preAllocSize设置为500就足够了。
minSessionTimeout maxSessionTimeout 这两个参数有默认值,分别是参数tickTime值的2倍和20倍,即默认的会话超时时间在2tickTime~20tickTime范围内,单位毫秒,剋有不配置,不支持系统属性方式配置。这两个参数用于服务端对客户端会话的超时时间进行限制,如果客户端设置的超时时间不在该范围内,那么会被服务端强制设置为最大或最小超时时间。
maxClientCnxns 该参数有默认值:60,可以不配置,不支持系统属性方式配置。从Socket局面限制单个客户端与单台服务器之间的并发连接数,即以IP地址粒度来进行连接数的限制。如果将该参数设置为0,则表示对连接数不做任何限制。需要注意该连接数限制选项的使用范围,其仅仅是对单台客户端机器与单台ZooKeeper服务器之间的连接数限制,并不能控制所有客户端的连接数综合。另外,在3.4.0版本以前该参数的默认值都是10,从3.4.0版本开始变成了60,因此运维人员尤其需要注意这个变化,以防ZooKeeper版本变化带来服务端连接限制变化的隐患。
jute.maxbuffer 该参数有默认值:1048575,单位是字节,可以不配置,仅支持系统属性方式配置:jute.maxbuffer。该参数用于配置单个数据节点(ZNode)上可以存储的最大数据量大小。通常情况下,运维人员不需要改动该参数,同时考虑到ZooKeeper上不适宜存储太多的数据,往往还需要将该参数设置的更小。需要注意的是,在变更参数的时候,需要在ZooKeeper集群的所有机器以及所有的客户端上均设置才能生效。
clientPortAddress 该参数没有默认值:可以不配置,不支持系统属性方式配置。针对那些多网卡的机器,该参数允许为每个IP地址指定不同的监听端口。
server.id=host:port:port 该参数没有默认值,在单机模式下剋有不配置,不支持系统属性方式配置。该参数用于配置组成ZooKeeper集群的机器列表,其中id即为ServerID,与每台服务器myid文件中的数字相对应。同时,在该参数中,会配置两个端口:第一个端口用于指定Follower服务器与Leader进行运行时通信和数据同步时所使用的端口、第二个端口则专门用于进行Leader选举过程中的投票通信。在ZooKeeper服务器启动的时候,其会根据myid文件中配置的Server ID来确定自己是哪台服务器,并使用对应配置的端口来进行启动。如果在实际使用过程中,需要在同一台服务器上部署多个ZooKeeper实例来构成伪集群的话,那么这些端口都需要配置成不同,例如:server.1=192.168.0.1:2777:3777server.2=192.168.0.1:2888:3888server.3=192.168.0.1:2999:3999
autopurge.snapRetainCount 该参数有默认值:3,可以不配置,不支持系统属性方式配置。从3.4.0版本开始,ZooKeeper提供了对历史事务日志和快照数据自动清理的支持。参数autopurge.snapRetainCount用于配置ZooKeeper在自动清理的时候需要保留的快照数据文件数量和对应的事务日志文件。需要注意的是,并不是磁盘上的所有事务日志和快照数据文件都可以被清理掉——那样的话将无法恢复书v。因此参数autopurge.snapRetainCount的最小值是3,如果配置autopurge.snapRetainCount值比3小的话,那么会被自动调整到3,即至少需要保留3个快照数据文件和对应的事务日志文件。
autopurge.purgeInterval 该参数有默认值:0,单位是小时,可以不配置,不支持系统属性方式配置。参数autopurge.purgeInterval和参数autopurge.snapRetainCount配套使用,用于配置ZooKeeper进行历史文件自动清理的频率。如果配置该值为0或负数,那么就表明不需要开启定时清理功能。ZooKeeper默认不开启这项功能。
fsync.warningthresholdms 该参数有默认值:1000,单位是毫秒,可以不配置,仅支持系统属性方式配置:fsync.warningthresholdms。参数fsync.warningthresholdms用于配置ZooKeeper进行事务日志fsync操作时消耗时间的报警阈值。一旦进行一个fsync操作消耗的时间大于参数,fsync.warningthresholdms指定的值,那么就在日志中打印出报警日志。
forceSync 该参数有默认值:yes,可以不配置,可选配置项为“yes”和“no”,仅支持系统属性方式配置:zookeeper.forceSync。该参数用于配置ZooKeeper服务器是否在事务提交的时候,将日志写入操作强制刷入磁盘(即调用java.nio.channels.FileChannel.force接口),默认情况下是“yes”,即每次事务日志写入操作都会实时刷入磁盘。如果将其设置为“no”,则能一定程度的提高ZooKeeper的写性能,但同时也会存在类似于机器断电这样的安全风险。
globalOutstandingLimit 该参数有默认值:1000,可以不配置,仅支持系统属性方式配置:zookeeper.globalOutstandingLimit。参数globalOutstandingLimit用于配置ZooKeeper服务器最大请求堆积数量。在ZooKeeper服务器运行的过程中,客户端会源源不断的将请求发送到服务端,为了防止服务端资源(包括CPU、内存和网络等)耗尽,服务端必须限制同时处理的请求数,即最大请求堆积数量。
leaderServes 该参数有默认值:yes,可以不配置,可选配置项为“yes”和“no”,仅支持系统属性方式配置:zookeeper.leaderServers。该参数用于配置Leader服务器是否能够接受客户端的连接,即是否允许Leader向客户端提供服务,默认情况下,Leader服务器能够接受并处理客户端的所有读写请求。在ZooKeeper的架构设计中,Leader服务器主要用来进行事务更新请求的协调以及集群本身的运行时协调,因此,可以设置让Leader服务器不接受客户端的连接,以使其专注于进行分布式协调。
SkipAcl 该参数有默认值:no,可以不配置,可选配置项为“yes”和“no”,仅支持系统属性方式配置:zookeeper.skipACL。该参数用于配置Leader服务器是否跳过ACL权限检查,默认情况下是“no”,即会对每一个客户端请求进行权限检查。如果将其设置为“yes”,则能一定程度的提高能够接受客户端的连接,即是否允许Leader向客户端提供服务,默认情况下ZooKeeper的读写性能,但同时也将向所有客户端开放ZooKeeper的数据,包括那些之前设置过ACL权限的数据节点,也将不再接受权限控制。
cnxTimeout 该参数有默认值:5000,单位是毫秒,可以不配置,仅支持系统属性方式配置:zookeeper.cnxTimeout。该参数用于配置在Leader选举过程中,各服务器之间进行TCP连接创建的超时时间。
electionAlg 在之前的版本中,可以使用该参数来配置选择ZooKeeper进行Leader选举时所使用的算法,但从3.4.0版本开始,ZooKeeper废弃了其他选举算法,只留下了FastLeaderElection算法,因此该参数目前看来没有用了。
Luckylau wechat
如果对您有价值,看官可以打赏的!