1 学习目标
- zookeeper是什么?有什么特点?
- zookeeper能做什么?
- zookeeper工作原理
- 安装部署和常用命令列表
- zookeeper集群方案
- zookeeper常见故障及解决方法
- 与其他类似服务对比:consul eureka
2 概念
zookeeper是一个分布式的、开源的程序协调服务,是 hadoop 项目下的一个子项目。致力于提供高性能、高可用、顺序一致性的分布式协调服务,保证数据最终一致性。主要功 能包括:配置管理、名字服务、分布式锁、集群管理。
2.1 主要功能介绍
- 配置管理
在我们的应用中除了代码外,还有一些就是各种配置。比如数据库连接等。一般我们都 是使用配置文件的方式,在代码中引入这些配置文件。当我们只有一种配置,只有一台服务 器,并且不经常修改的时候,使用配置文件是一个很好的做法,但是如果我们配置非常多, 有很多服务器都需要这个配置,这时使用配置文件就不是个好主意了。这个时候往往需要寻 找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的 都可以获得变更。Zookeeper 就是这种服务,它使用 Zab 这种一致性协议来提供一致性。现 在有很多开源项目使用 Zookeeper 来维护配置,比如在 HBase 中,客户端就是连接一个 Zookeeper,获得必要的 HBase 集群的配置信息,然后才可以进一步操作。还有在开源的消 息队列 Kafka 中,也使用 Zookeeper来维护broker的信息。在 Alibaba开源的 SOA 框架Dubbo 中也广泛的使用 Zookeeper 管理一些配置来实现服务治理。
- 命名服务
命名服务这个就很好理解了。比如为了通过网络访问一个系统,我们得知道对方的 IP 地址,但是 IP 地址对人非常不友好,这个时候我们就需要使用域名来访问。但是计算机是 不能是域名的。怎么办呢?如果我们每台机器里都备有一份域名到 IP 地址的映射,这个倒 是能解决一部分问题,但是如果域名对应的 IP 发生变化了又该怎么办呢?于是我们有了 DNS 这个东西。我们只需要访问一个大家熟知的(known)的点,它就会告诉你这个域名对应 的 IP 是什么。在我们的应用中也会存在很多这类问题,特别是在我们的服务特别多的时候, 如果我们在本地保存服务的地址的时候将非常不方便,但是如果我们只需要访问一个大家都 熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。
- 分布式锁
Zookeeper 是一个分布式协调服务。这样我们就可以利 用 Zookeeper 来协调多个分布式进程之间的活动。比如在一个分布式环境中,为了提高可靠 性,我们的集群的每台服务器上都部署着同样的服务。但是,一件事情如果集群中的每个服 务器都进行的话,那相互之间就要协调,编程起来将非常复杂。而如果我们只让一个服务进 行操作,那又存在单点。通常还有一种做法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即 fail over 到另外的服务。这在很多分布式系统 中都是这么做,这种设计有一个更好听的名字叫 Leader Election(leader 选举)。比如 HBase 的 Master 就是采用这种机制。
- 集群管理
在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些 节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中其他机 器需要感知到这种变化,然后根据这种变化做出对应的决策。比如我们是一个分布式存储系 统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候我们要根据现在集群目 前的状态来分配存储节点。这个时候我们就需要动态感知到集群目前的状态。还有,比如一 个分布式的 SOA 架构中,服务是一个集群提供的,当消费者访问某个服务时,就需要采用 某种机制发现现在有哪些节点可以提供该服务(这也称之为服务发现,比如 Alibaba 开源的 SOA 框架 Dubbo 就采用了 Zookeeper 作为服务发现的底层机制)。还有开源的 Kafka 队列就 采用了 Zookeeper 作为 Cosnumer 的上下线管理。
2.2 特点
- 高性能(简单的数据模型)
- 采用树形结构组织数据节点;
- 全量数据节点,都存储在内存中;
- Follower 和 Observer 直接处理非事务请求;
- 高可用(构建集群)
- 半数以上机器存活,服务就能正常运行
- 自动进行 Leader 选举
- 顺序一致性(事务操作的顺序)
- 每个事务请求,都会转发给 Leader 处理
- 每个事务,会分配全局唯一的递增zxid,其中,zxid是ZAB协议的事务编号
- 同一个 Client 发起的事务请求,严格按照发起顺序执行
- 最终一致性
- 通过提议投票方式,保证事务提交的可靠性
- 提议投票方式,只能保证 Client 收到事务提交成功后,半数以上节点能够看到最新数据
2.3 ZAB协议
全称 ZooKeeper Atomic Broadcast, 即ZooKeeper原子消息广播协议。zookeeper集群节点通过 Zab 协议(Zookeeper Atomic Broadcast)来保持数据的一致性。
- 特性
Zab 协议需要确保那些已经在 Leader 服务器上提交(Commit)的事务 最终被所有的服务器提交。
Zab 协议需要确保 丢弃 那些只在 Leader 上被提出而没有被提交的事务。
- 原理
Zab协议要求每个 Leader 都要经历三个阶段:发现,同步,广播。
- 发现:要求zookeeper集群必须选举出一个 Leader 进程,同时 Leader 会维护一个 Follower 可用客户端列表。将来客户端可以和这些 Follower节点进行通信。
- 同步:Leader 要负责将本身的数据与 Follower 完成同步,做到多副本存储。这样也是提现了高可用和分区容错。Follower将队列中未处理完的请求消费完成后,写入本地事务日志中。
- 广播:Leader 可以接受客户端新的事务Proposal请求,将新的Proposal请求广播给所有的 Follower。
ZAB 协议包括两种基本的模式,分别是崩溃恢复和消息广播。
当整个服务框架在启动过程中,或是当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB 协议就会进入恢复模式并选举产生新的 Leader 服务器。
当选举产生了新的 Leader 服务器,同时集群中已经有过半的机器与该 Leader 服务器完成了状态同步之后,ZAB 协议就会退出恢复模式。
其中,所谓的状态同步是指数据同步,用来保证集群中存在过半的机器能够和 Leader 服务器的数据状态保持一致。当集群中已经有过半的 Follower 服务器完成了和 Leader 服务器的状态同步,那么整个服务框架就可以进人消息广播模式了。
当一台同样遵守 ZAB 协议的服务器启动后加入到集群中时,如果此时集群中已经存在一个 Leader 服务器在负责进行消息广播。
那么新加入的服务器就会自觉地进人数据恢复模式:找到 Leader 所在的服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。正如上文介绍中所说的,ZooKeeper 设计成只允许唯一的一个 Leader 服务器来进行事务请求的处理。
Leader 服务器在接收到客户端的事务请求后,会生成对应的事务提案并发起一轮广播协议。而如果集群中的其他机器接收到客户端的事务请求,那么这些非 Leader 服务器会首先将这个事务请求转发给 Leader 服务器。
2.4 存储结构
- Znode
在 Zookeeper 中,znode 是一个跟 Unix 文件系统路径相似的节点,可以往这个节点存储 或获取数据。 Zookeeper 底层是一套数据结构。这个存储结构是一个树形结构,其上的每一个节点, 我们称之为“znode” zookeeper 中的数据是按照“树”结构进行存储的。而且 znode 节点还分为 4 中不同的类 型。 每一个 znode 默认能够存储 1MB 的数据(对于记录状态性质的数据来说,够了) 可以使用 zkCli 命令,登录到 zookeeper 上,并通过 ls、create、delete、get、set 等命令 操作这些 znode 节点
- Znode 节点类型
- PERSISTENT 持久化节点: 所谓持久节点,是指在节点创建后,就一直存在,直到 有删除操作来主动清除这个节点。否则不会因为创建该节点的客户端会话失效而消失。
- PERSISTENT_SEQUENTIAL 持久顺序节点:这类节点的基本特性和上面的节点类 型是一致的。额外的特性是,在 ZK 中,每个父节点会为他的第一级子节点维护一份时序, 会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属 性,那么在创建节点过程中,ZK 会自动为给定节点名加上一个数字后缀,作为新的节点名。 这个数字后缀的范围是整型的最大值。 在创建节点的时候只需要传入节点 “/test_”,这样 之后,zookeeper 自动会给”test_”后面补充数字。
- EPHEMERAL 临时节点:和持久节点不同的是,临时节点的生命周期和客户端会 话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提 到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。 这里还要注意一件事,就是当你客户端会话失效后,所产生的节点也不是一下子就消失 了,也要过一段时间,大概是 10 秒以内,可以试一下,本机操作生成节点,在服务器端用 命令来查看当前的节点数目,你会发现客户端已经 stop,但是产生的节点还在。
- EPHEMERAL_SEQUENTIAL 临时自动编号节点:此节点是属于临时节点,不过带 有顺序,客户端会话结束节点就消失。
2.4.1 内存数据
- DataTree
DataTree是内存数据存储的核心,是一个树结构,代表了内存中一份完整的数据。DataTree不包含任何与网络、客户端连接及请求处理相关的业务逻辑,是一个独立的组件。- DataNode
DataNode是数据存储的最小单元,其内部除了保存了结点的数据内容、ACL列表、节点状态之外,还记录了父节点的引用子节点列表两个属性,其他提供了对子节点列表进行操作的接口。- ZKDatabase
Zookeeper的内存数据库,管理Zookeeper的所有会话、DataTree存储和事务日志。ZKDatabase会定进向磁盘dump快照数据,同时在Zookeeper启动时,会通过磁盘的事务日志和快照文件恢复一个完整的内存数据库。
2.4.2 磁盘数据
- 事务日志
在配置Zookeeper集群时需要配置dataDir目录,其用来存储事务日志文件。也可以为事务日志单独分配一个文件存储目录:dataLogDir。
在zookeeper运行过程中,可能出现非Leader记录的事务ID比Leader上大,这是非法运行状态。此时,需要保证所有机器必须与该Leader的数据保持同步,即Leader会发送TRUNC命令给该机器,要求进行日志截断,Learner收到该命令后,就会删除所有包含或大于该事务ID的事务日志文件。
- 快照数据
数据快照是Zookeeper数据存储中非常核心的运行机制,数据快照用来记录Zookeeper服务器上某一时刻的全量内存数据内容,并将其写入指定的磁盘文件中。Zookeeper快照文件也可以指定磁盘目录,通过dataDir属性来配置。
- zookeeper初始化流程
数据的初始化工作是从磁盘上加载数据的过程,主要包括从快照文件加载快照和根据事务日志进行数据修正两个过程。
1)初始化FileTxnSnapLog,FileTxnSnapLog是Zookeeper事务日志和快照数据访问层,用于衔接上层业务和底层数据存储。
2)初始化ZKDatabase。首先构建DataTree
3)创建playbacklistener。在Zookeeper数据恢后期,会有事务修正过程,此过程会回调playbacklistener来进行对应的数据修正。
4)处理快照文件。
5)获取最新的100个快照文件。
6)解析快照文件,逐个解析快照文件,此时需要进行反序列化,生成DataTree和SessionsWithTimeouts,同时还会检验Checksum及快照文件的正确性。通常只会解析最新的正确的快照文件。若100个快照文件解析完后还是无法成功恢复一个完整的DataTree和sessionWithTimeouts,此时服务器启动失败。
7)获取最新的ZXID,此时根据快照文件的文件名即可解析出最新的ZXID:zxid_for_snap。
8)处理事务日志。此时服务器内存中已经有了一份近似全量的数据,现在开始通过事务日志来更新新增数据。
9)获取所有zxid_for_snap之后提交的事务。
10)事务应用。获取大于zxid_for_snap的事务后,将其逐个应用到之前基于快照数据文件恢复出来DataTree和sessionWithTimeous。每当有一个事务被应用到内存数据库中后,Zookeeper同时会回调PlayBackListener,将这事务操作记录转换成Proposal,并保存到ZKDatabase和committedLog中,以便Follower进行快速同步。
11)获取最新的ZXID。
12)检验epoch。epoch标识了当前Leader周期,集群机器相互通信时,会带上这个epoch以确保彼此在同一个Leader周期中。完成数据加载后,Zookeeper会从步骤11中确定ZXID中解析出事务处理的Leader周期,同进也会从磁盘的currentEpoch和acceptedEpoch文件中读取上次记录的最新epoch值,进行检验。
3 集群
- 3种角色
leader:负责进行投票的发起和决议,更新系统状态。一个集群只有一个leader,它会发起并维护与各 Follwer 及Observer间的心跳,只有leader负责处理外部客户端的事物请求(或写操作),再由 Leader 将写操作广播给follower,然后等待follower的反馈。在ZAB协议中,只要超过半数follower节点反馈OK,Leader节点就会向所有的follower服务器发送commit消息。即将leader节点上的数据同步到follower节点之上。
follower:一个Zookeeper集群可能同时存在多个Follower,它会响应Leader的心跳。Follower可直接处理并返回客户端的读请求,同时会将写请求转发给Leader处理。并且负责在Leader处理写请求时对请求进行投票。
observer:角色与Follower类似,但是无投票权。Zookeeper需保证高可用和强一致性,为了支持更多的客户端,需要增加更多 Server;Server 增多,投票阶段延迟增大,影响性能;引入 Observer, Observer不参与投票; Observers接受客户端的连接,并将写请求转发给leader节点; 加入更多Observer节点,提高伸缩性,同时不影响吞吐率。
- 4个状态
leading:当前Server即为选举出来的leader。领导者状态。
following:leader已经选举出来,当前Server与之同步。随从状态。
observing:同步leader状态,不参与投票。观察状态。
looking:当前Server不知道leader是谁,正在搜寻。竞选状态。
- Leader选举时机
选举是保证分布式数据一致性的关键所在。当Zookeeper集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举。
- 服务器初始化启动。
- 服务器运行期间无法和Leader保持连接。
- 集群启动时选举leader的过程
若进行Leader选举,则至少需要两台机器,这里选取3台机器组成的服务器集群为例。在集群初始化阶段,当有一台服务器Server1启动时,其单独无法进行和完成Leader选举,当第二台服务器Server2启动时,此时两台机器可以相互通信,每台机器都试图找到Leader,于是进入Leader选举过程。选举过程如下
- 每个Server发出一个投票。由于是初始情况,Server1和Server2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,此时Server1的投票为(1, 0),Server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。
- 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。
- 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下:
- 优先检查ZXID。ZXID比较大的服务器优先作为Leader。
- 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。
对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的ZXID,均为0,再比较myid,此时Server2的myid最大,于是更新自己的投票为(2, 0),然后重新投票,对于Server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。
- 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于Server1、Server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了Leader。
- 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。
- 服务器运行时期的Leader选举
当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于基于fast paxos算法实现的.
- 选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;
- 选举线程首先向所有Server发起一次询问(包括自己);
- 选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;
- 收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;
- 线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数,设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。
通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1.
每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。
fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。
- Leader主要功能
- 恢复数据;
- 维持与follower的心跳,接收follower请求并判断follower的请求消息类型;(Leader进程和所有与所有的Follower进程之间都通过心跳检测机制来感知彼此的情况)
- follower的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。
PING消息是指follower的心跳信息;
REQUEST消息是follower发送的提议信息,包括写请求及同步请求;
ACK消息是follower的对提议的回复,超过半数的follower通过,则commit该提议;
REVALIDATE消息是用来延长SESSION有效时间。
- Follower主要功能
- 向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
- 接收Leader消息并进行处理;
- 接收Client的请求,如果为写请求,发送给Leader进行投票;
- 返回Client结果。
Follower的消息循环处理如下几种来自Leader的消息:
- PING消息:心跳消息
- PROPOSAL消息:Leader发起的提案,要求Follower投票
- COMMIT消息:服务器端最新一次提案的信息
- UPTODATE消息:表明同步完成
- REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息
- SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。
4 安装部署及常用命令
4.1 实验环境
172.16.212.21 CentOS7 JDK1.8 zookeeper stable 3.6.3
172.16.212.22 CentOS7 JDK1.8 zookeeper stable 3.6.3
172.16.212.23 CentOS7 JDK1.8 zookeeper stable 3.6.3
4.2 操作手册
- 所有节点:安装java环境
不安装则启动时会报错:Error: JAVA_HOME is not set and java could not be found in PATH.
# 安装open jdk
yum install -y java
# 安装 oracle jdk
tar xvfz jdk-8u261-linux-x64.tar.gz -C /usr/local/
vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_261
export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
export PATH=$PATH:${JAVA_HOME}/bin
source /etc/profile
java -version
- 所有节点:部署zk
mkdir /opt/work && cd /opt/work
wget https://downloads.apache.org/zookeeper/stable/apache-zookeeper-3.6.3-bin.tar.gz
tar xvfz apache-zookeeper-3.6.3-bin.tar.gz
cd /opt/work/apache-zookeeper-3.6.3-bin
cp conf/zoo_sample.cfg conf/zoo.cfg
vim conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/data/zookeeper
clientPort=2181
server.1=172.16.212.21:9001:7001
server.2=172.16.212.22:9001:7001
server.3=172.16.212.23:9001:7001
mkdir -p /opt/data/zookeeper
vim /opt/data/zookeeper/myid
#172.16.212.21的内容为 1,172.16.212.22的内容为 2, 172.16.212.23的内容为 3
bash bin/zkServer.sh start
# 启动第一台的时候查看状态,会提示 Error contacting service. It is probably not running.
# 接着启动第二台,然后查看2台的状态就会发现 第二台已经变成了leader,第一台变成了follower,符合我们上面说的选举理论~
bash ./bin/zkServer.sh status
# 一开始启动失败了,看日志报错是:
错误: 找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain
# 原因是我下载的是没有编译过的 apache-zookeeper-3.6.3.tar.gz。。。大型自我无语事件!
- systemd管理zk
vim /etc/systemd/system/zookeeper.service
[Unit]
Description=zookeeper.service
After=network.target
[Service]
Type=forking
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/jdk1.8.0_261//bin:/usr/local/jdk1.8.0_261/bin"
ExecStart=/opt/work/apache-zookeeper-3.6.3-bin/bin/zkServer.sh start /opt/work/apache-zookeeper-3.6.3-bin/conf/zoo.cfg
ExecStop=/opt/work/apache-zookeeper-3.6.3-bin/bin/zkServer.sh stop
PIDFile=/opt/data/zookeeper/zookeeper_server.pid
Restart=on-failure
KillMode=none
User=root
Group=root
Restart=on-failure
[Install]
WantedBy=multi-user.target
# 停止zk
bash bin/zkServer.sh stop
# 使用systemd管理
systemctl enable zookeeper
systemctl start zookeeper
systemctl status zookeeper
4.3 配置详解
4.3.1 目录及用途
/opt/work/apache-zookeeper-3.6.3-bin/logs 日志文件
/opt/work/apache-zookeeper-3.6.3-bin/bin 常用命令脚本
/opt/work/apache-zookeeper-3.6.3-bin/conf 配置文件
4.3.2 配置文件详解
- 必须配置
tickTime
配置zookeeper中最小时间单元长度,单位毫秒。很多运行时的时间间隔都是用tickTime倍数表示,如zookeeper中会话最小超时时间默认2* tickTime。
dataDir
配置zookeeper存储快照文件的目录。
clientPort
当前zookeeper服务器对外的服务端口
- 一般配置
maxClientCnxns:
在套接字级别上限制同一客户端的并发连接数。因为同一客户端IP地址相同,可能会调度到同一个ZooKeeper服务器节点上。这个配置项是为了避免DoS攻击。默认值为60,设置为0表示不做任何限制。
clientPortAddress
指定为客户端提供服务的监听地址(ipv4/ipv6)。换句话说,clientPort将只绑定在地址上。如果不设置该选项,将默认监听在所有地址上(0.0.0.0)。
minSessionTimeout maxSessionTimeout
客户端和服务端会话保持的最小、最大超时时间。ZooKeeper的很多数据和状态都和会话绑定。假如客户端和服务端成功建立连接(会话)后,正常情况下,客户端会时不时地向服务端发送心跳,如果这个服务端或者客户端挂了,它们之间的会话要保持多长时间。
fsync.warningthresholdms
事务日志输出时,如果调用fsync方法超过此处指定的超时时间,那么会在日志中输出警告信息。默认是1000ms。
syncEnabled
指定观察者(observers)是否像follower一样,也记录事务日志和快照,以便在observers重启时能加速恢复。默认值为true,设置为false表示禁用该功能,不记录日志和快照。
- 集群配置
initLimit
配置leader等待follower启动,并完成数据同步的时间,默认值10,表示10倍tickTime的时间。通常使用默认值即可,随着zookeeper集群管理数据量增大,follower启动并同步leader上数据的时间也会变长,此时可适当调大该参数值。
syncLimit
用于配置leader和follower之间心跳检测的最大时间延时时间,默认5,表示5倍tickTime的时间。通常使用默认值即可,随着zookeeper集群的网络质量降低,可适当调大该参数。
server.id=host:port:port
该参数在单机模式下不可配置,用于配置组成zookeeper集群的机器列表。其中id为ServerID,与每台zookeeper服务器myid中的数值一致;host为当前zookeeper服务器机器名或ip地址;第一个port用于指定follower与leader进行通信和数据同步所使用的tcp端口;第二个port指定leader选举中投票通信的tcp端口。
Zookeeper启动时会根据myid中配置的ServerID来确定自己是那台服务器,并使用配置的对应端口启动,如果在一台服务器上部署多个zookeeper构成伪集群的话,所有端口都要配成不同的哦。
electionAlg
指定leader选举算法。默认值为3,表示使用基于TCP的快速选举。在以前的版本中,还有0/1/2三种算法,它们都是基于UDP的,已经废弃了,以后的版本中会移除这三种算法。
leaderServes
默认值为yes,表示leader也接受客户端的连接,接受来自客户端的读、写请求。leader的主要作用是协调ZooKeeper集群服务器节点间的写操作,如果想要获取更高的写吞吐量,可以将其设置为no,这样leader将不允许客户端的连接,它将专注于协调,但这会损失一点读吞吐量。
cnxTimeout
在投票选举新的leader时,需要通过选举端口建立连接来发送通知信息。该配置项设置打开这个连接的超时时长。默认值为5。
ipReachableTimeout
3.4.11版本中才引入的配置项。当解析主机名时,为可访问的IP地址设置此超时值,单位毫秒。默认情况下,ZooKeeper将使用主机名的第一个IP地址(不做任何reachable检查)。设置ipReachableTimeout(大于0)后,ZooKeeper将尝试获取第一个可访问的IP地址。这是通过调用Java API函数InetAddress.isreavailable(long timeout)实现的。其中使用了这个超时值。如果找不到这样的IP地址,主机名的第一个IP地址将被使用。
- 事务日志和快照配置
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,表示不开启自动清理功能。
4.4 常用命令
- 集群操作
#连接集群
apache-zookeeper-3.6.3-bin/bin/zkCli.sh -server 127.0.0.1:2181
#启动服务
bin/zkServer.sh start
bin/zkServer.sh restart
#停止服务
bin/zkServer.sh stop
#查看服务状态
bin/zkServer.sh status
- 数据操作
h 显示所有命令
ls path 查看某个节点下的所有子节点信息
stat path 获取指定节点的状态信息
get path 获取当前节点的数据内容
quit 退出客户端
# -s 表示是顺序节点,-e 标识是临时节点,path 节点路径,data 节点数据,acl 节点权限
create [-s] [-e] path data acl
# 修改当前节点的数据内容 如果指定版本,需要和当前节点的数据版本一致
set path data [version]
# 删除指定路径的节点 如果有子节点要先删除子节点
delete path [version]
# 删除当前路径节点及其所有子节点
rmr path
# 设置节点配额(比如限制节点数据长度,限制节点中子节点个数),-n 是限制子节点个数 -b是限制节点数据长度,超出配额后,ZooKeeper不会报错,而是在日志信息中记录
setquota -n|-b val path
# 查看路径节点的配额信息
listquota path
# 删除节点路径的配额信息
delquota [-n|-b] path
# 查看客户端这次会话所执行的所有命令 和 执行指定历史命令
history 和 redo cmdno
5 常见故障及解决办法
- ./bin/zkServer.sh start-foreground
使用这个命令启动zk,可以看到更详细的启动信息
- logs/zookeeper.out
是zk的日志文件,可以据此排查问题
- zkServer.sh status
也能看到可用于排错的信息
- myid文件很重要
位于dataDir配置的路径下,文件中只有1个字符串,且每个节点的id不同
6 类比其他注册服务
- CAP理论是分布式架构中重要理论
- 一致性(Consistency) (所有节点在同一时间具有相同的数据)
- 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
- 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)