目录
基本介绍
软件定义
Zookeeper 是由Apache Hadoop的子项目发展而来, Hadoop是一个黄色大象玩具的名字,而ZooKeeper则是动物管理员。
1、Zookeeper是一个开源的分布式应用程序协调服务,本质上是一个分布式的小文件存储系统。
2、Zookeeper以文件目录树的方式存储数据,数据都会加载到内存,其功能比较完善,能增删改查、能做消息队列、还能提供分布式锁、ACL权限管控、事务处理等,有点类似于一个内存数据库,可以为集群提供快速的响应服务。
3、个人简单的总结:Zookeeper = 数据结构(Znode)+ 监听机制 (Watcher) + 会话(Session)
PS:ZooKeeper通过对数据结构树中的Znode文件进行有效管理,通过维护、监控存储数据的状态变化,实现基于文件数据的集群管理。
服务请求
1、事务性请求:在zookeeper中的事务请求简单说就是 写操作,比如更新、新增、删除等影响数据的操作,需要保证操作在整个集群内的事务性,这些操作就是事务性请求。
2、非事务性请求:比如查询操作 这些不影响数据的操作,这些操做就是非事务性请求。
应用场景
1、统一的命名服务:在分布式环境下,经常需要对应用/服务进行统一命名 ,便于识别。例如:IP 不容易记住,而域名容易记住。
2、分布式配置中心:可将配置信息写入 zookeeper 上的一个 znode,然后客户端监听到配置变更后,会自动把相同的配置文件同步更新。
3、集群管理:通过zookeeper临时节点创建与自动删除来掌握服务节点的动态增减。Leader角色服务主机会将变更的节点信息通知到集群里的各个Follower角色主机,然后重新选举Leader。
4、分布式锁:分布式锁的场景主要也是用在分布式服务中,多节点中想要锁住共享资源,zookeeper是其中的一个选择,使用zookeeper实现分布式锁主要用了它的临时序列节点的机制。
5、发布/订阅:类似于消息队列,发布者把数据存在znode节点上,订阅者会读取这个数据。
场景案例
ZooKeeper最典型的使用案例就是Hadoop,Hadoop 中的NameNode与YARM 的ResourceManager 都是使用了Zookeeper 进行集群管理,简单介绍两个场景:
场景一:基于zookeeper 的数据结构(Znode)+ 监听机制 (Watcher) + 会话(Session) + 分布式锁,实现了NameNode与ResourceManager主备管理;
场景二:基于zookeeper 的数据结构(Znode)+ 监听机制 (Watcher) + 会话(Session),实现了ResourceManager 中的RMstateStore 运行状态信息数据处理。
数据模型(Znode)
在谈到分布式的时候,我们通常说的“节点”是指组成集群的每一台机器。然而在ZooKeeper中,“节点”分为两类:
第一类是指构成集群的机器,我们称之为机器节点;
第二类则是指数据模型中的数据单元,我们称之为数据节点Znode。每个Znode上都会保存自己的数据内容,同时还会保存一系列属性信息。
zookeeper 数据模型的结构与Linux文件系统很类似,都是树形的数据结构。zookeeper中每一个子目录项都是一个znode(目录节点),这些目录节点和我们普通的目录一样可以新建、删除、修改,四种类型znode包含:
1、持久化目录节点:客户端与zookeeper断开连接后,该节点依旧存在,只要不手动删除该节点,他将永远存在。
2、持久化顺序编号目录节点:客户端与zookeeper断开连接后,该节点依旧存在,只是zookeeper给该节点名称进行顺序编号。
3、临时目录节点:客户端与zookeeper断开连接后,该节点被删除。
4、临时顺序编号目录节点:客户端与zookeeper断开连接后,该节点被删除,只是zookeeper给该节点名称进行顺序编号。
监听机制 (Watcher)
1、Watcher 监听:是 zookeeper 中非常重要的特性,基于zookeeper 上创建的节点,可以对这些节点绑定监听事件。比如可以监听节点数据变更、节点删除、子节点状态变更等事件,通过这个事件机制,可以实现:基于 zookeeper 实现分布式锁、集群管理等功能;
2、Watcher 特性:当数据发生变化的时候,zookeeper 会产生一个 watcher 事件,并且会发送到客户端。但是客户端只会收到一次通知。如果后续这个节点再次发生变化,那么之前设置 watcher 的客户端不会再次收到消息(watcher 是一次性的操作),可以通过循环监听去达到永久监听效果。
会话(Session)
Session是指客户端会话,在讲解会话之前,我们首先来了解一下客户端连接。在ZooKeeper中,一个客户端连接是指客户端和服务器之间的一个TCP长连接。ZooKeeper对外的服务端口默认是2181,客户端启动的时候,首先会与服务器建立一个TCP连接,从第一次连接建立开始,客户端会话的生命周期也开始了,通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向ZooKeeper服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的Watch事件通知。Session的sessionTimeout值用来设置一个客户端会话的超时时间。当由于服务器压力太大、网络故障或是客户端主动断开连接等各种原因导致客户端连接断开时,只要在sessionTimeout规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。
集群角色
Leader(主节点、领导)
Leader是整个ZK集群的核心,负责响应所有对Zookeeper状态变更的请求。它会将每个状态更新请求进行排序和编号,以便保证整个集群内部消息处理的FIFO(First Input First Output的缩写,先入先出队列)。
主要功能包含:
1、集群内部各服务器的调度者。
2、处理事务请求(CUD)和非事务请求。
PS:Leader是ZK中唯一一个有权对事务请求进行调度和处理的角色,能够保证集群事务处理的顺序。如果client发送事务请求到其他从节点server上,最终这个事务请求也会被从节点转发至Leader节点处理,由Leader决定该事务编号、执行的操作。
Follower(从节点、跟随者、下属)
主要功能包含:
1、处理client非事务请求,如果client发出的请求是事务请求,会转发给Leader。
2、参与集群对Leader选举投票(ZK中leader是通过投票选举出来的)。
3、参与事务请求 Proposal 的投票(leader发起的提案,要求follower投票,需要半数以上follower节点通过,leader才会commit数据);
PS:在ZooKeeper的实现中,每一个事务请求都需要集群中过半机器投票认可才能被真正应用到ZooKeeper的内存数据库中去,这个投票与统计过程被称为“Proposal流程”。
Observer(从节点、观察者、下属)
1、Observer除了不参与Leader选举投票外,与Follower作用相同。
PS:通常用于在不影响集群事务处理能力的前提下,提升集群的非事务处理能力。简单来说,observer可以在不影响集群写(CUD)性能的情况下,提升集群读(R)性能,并且因为它不参与投票,所以他们不属于ZooKeeper集群的关键部位,即使他们failed,或者从集群中断开,也不会影响集群的可用性。
集群选举
选举机制
Leader选举是保证分布式数据一致性的关键所在。当Zookeeper集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举。
1、服务器初始化启动
2、服务器运行期间无法和Leader保持连接(Leader挂掉了)
选举算法
LeaderElection
AuthFastLeaderElection
FastLeaderElection(最新默认):采用 投票数大于半数则胜出 的逻辑
选举内容
在选举过程中,需要将投票信息发送给集群中的所有服务器,它包含如下内容:
sid(服务器ID):在同一集群中,每一台服务器都有自己的myid,并且该id不能重复。该id编号越大,在选举算法中,该服务器的权重就越大(越容易成为leader)。
zxid(最新事务id):初始值0,每一个服务器值发生变化,该值会递增。若该值越大,说明该服务器的数据越新,在选举算法中数据越新,其权重就越大。
epoch(逻辑时钟):也叫投票次数,从0开始递增。同一轮投票过程中,各个机器的逻辑时钟值是相同的。每投完一次票,该值就会增加,然后与接收到的其他服务器返回的投票信息中的数据相对比。以此来判断其他机器的投票信息是否是最新的。(举个栗子:某台服务器在投票选举过程中,突然在某轮投票时因网络延迟,暂时挂掉了,投票未成功。那么该服务器逻辑时钟值肯定就会小于其他正常的服务器,也因此,该服务器的选举权重变小了。)
state(服务状态):
Looking(选举状态)
Leading(领导者状态,表明当前server是leader)
Following(跟随者状态,表明当前server是Follower)
Observing(观察者状态、表明当前server是Observer)。
选举步骤
当系统启动或者leader崩溃后,就会开始leader的选举。
1、zxid越大,表示数据最新,会被优先选举成新的leader;
2、如果zxid都一样,此时选择myid最大的节点成为新的leader;
3、electionEpoch:逻辑时钟,用来判断多个投票是否在同一轮选举周期中,该值在服务端是一个自增序列,每次进入新一轮的投票后,都会对该值进行加1操作;
4、peerEpoch:被推举的Leader的epoch;
5、state:当前服务器的状态。
根据默认算法统计投票。每次投票后,服务器统计投票信息,如果有过半机器接收到相同的投票,那么leader产生,如果否,那么进行下一轮投票;
改变server状态。一旦确定了Leader,server会更新自己的状态为Following或者是Leading。选举结束。
PS:Zookeeper分布式模式安装,通常由 奇数 台servers组成。原因是保证Leader选举能够得到多数的支持。(基于Paxos算法的实现,在选举Leader时或者在Leader事务处理时,需要获取半数以上的投票才能执行)
PS:为什么坏一台Leader主机就影响业务?
一句话总结:在业务事务执行率高的情况下有轻微的影响。
原因是基于Paxos算法的实现,在选举Leader时或者在Leader事务处理时,需要获取半数以上的投票才能执行,所以任务提交有一个执行过程。
只有在确保那些已经在 Leader 提交的事务最终会被所有服务器提交,
或者确保丢弃那些只在 Leader 提出、复制,但没有提交的事务的情况下才对业务使用没有影响。
集群安装
安装jdk环境
#官网下载地址:
https://www.oracle.com/technetwork/java/javase/downloads/index.html
#解压:
tar -zxf jdk-8u181-linux-x64.tar.gz -C /opt/
#配置环境变量,在/etc/profile最后一行添加,也就是指定相应的文件的位置:
export JAVA_HOME=/opt/java/jdk1.8.0_181
export CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
安装zookeeper集群
#在官网下载软件包,执行以下命令:
wget https://mirror-hk.koddos.net/apache/zookeeper/zookeeper-3.5.9/apache-zookeeper-3.5.9-bin.tar.gz --no-check-certificate
#解压
tar -zxf apache-zookeeper-3.5.9-bin.tar.gz -C /opt/
mv apache-zookeeper-3.5.9-bin zookeeper
#创建数据存储目录
mkdir -p /opt/zookeeper/zkdata
#配置服务启动文件
cp /opt/zookeeper/zoo_sample.cfg /opt/zookeeper/zoo.cfg
vi /opt/zookeeper/zoo.cfg
# Client-Server通信心跳时间
# Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。tickTime以毫秒为单位。
tickTime=2000
# Leader-Follower初始通信时限
# 集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量)。
initLimit=10
# Leader-Follower同步通信时限
# 集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量)
syncLimit=5
# 数据文件目录
# Zookeeper保存数据的目录,默认情况下,Zookeeper将写数据的日志文件也保存在这个目录里。
dataDir=/opt/zookeeper/zkdata
# 客户端连接端口
# 客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
clientPort=2181
# 对于一个客户端的连接数限制,默认是60,这在大部分时候是足够了。但是在我们实际使用中发现,在测试环境经常超过这个数,经过调查发现有的团队将几十个应用全部部署到一台机器上,以方便测试,于是这个数字就超过了。
# maxClientCnxns=60
# 服务器名称与地址:集群信息(server.服务器编号,服务器地址,集群内部通信端口,选举端口)这个配置项的书写格式比较特殊,规则如下:
# server.N=YYY:A:B
# server.1=192.168.3.180:2888:3888
# server.2=192.168.3.181:2888:3888
# server.3=192.168.3.182:2888:3888
# autopurge.snapRetainCount、autopurge.purgeInterval -- 客户端在与zookeeper交互过程中会产生非常多的日志,而且zookeeper也会将内存中的数据作为snapshot保存下来,这些数据是不会被自动删除的,这样磁盘中这样的数据就会越来越多。不过可以通过这两个参数来设置,让zookeeper自动删除数据。autopurge.purgeInterval就是设置多少小时清理一次。而autopurge.snapRetainCount是设置保留多少个snapshot,之前的则删除。
# autopurge.snapRetainCount=3
# autopurge.purgeInterval=1
#配置集群myid
echo "1" >/opt/zookeeper/zkdata/myid
#配置完毕后在将该zookeeper 文件夹拷贝到其它主机。然后再修改myid 就可以启动了。
常用命令
// 以下命令,都在 zookeeper目录 下执行
./bin/zkServer.sh start (启动zk服务器)
./bin/zkServer.sh status (查看zk服务器状态)
./bin/zkServer.sh stop (停止zk服务器)
./bin/zkServer.sh restart (重启zk服务器)
./bin/zkCli.sh -server 【ip:port】 (使用客户端连接服务端,如:./bin/zkCli.sh -server 127.0.0.1:2181。连接本机zk服务器)
// 以下命令,都在zk客户端执行
// 节点操作相关
create [-s] [-e] path data [acl] 创建节点
ls [-s] [-w] [-R] path 查询节点下的子节点列表
get [-s] [-w] path 获取目标节点的值以及属性
set [-s] [-v version] path data 更新节点数据
delete [-v version] path 删除目标节点(该目标节点不能有子节点)
deleteall path 删除目标节点以及目标节点的子节点
// 其他命令
客户端状态下 ctrl+c 退出客户端
quit (退出客户端)
help (查看客户端帮助命令)
setquota -n|-b val path 给节点添加限制
listquota path 列出目标节点的限制
delquota [-n|-b] path 删除目标节点的限制
history 列出最近十次的历史命令
redo cmdno 重新执行指定命令编号的历史命令(一般与history连接使用)
stat [-w] path 查询节点状态
getAcl [-s] path 查询节点ACL权限
addauth digest <user>:<password> 给上下文添加一个认真用户
setAcl [-s] [-v version] [-R] path auth:<user>:<acl>
auth模式设置节点ACL权限
setAcl [-s] [-v version] [-R] path digest:<用户>:<密文>:<acl>
digest模式设置节点ACL权限
下一篇:
参考: