1. zookeeper是什么?
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
2. zookeeper能做什么?
Apache ZooKeeper是由集群(节点组)使用的一种服务,用于在自身之间协调,并通过稳健的同步技术维护共享数据。ZooKeeper本身是一个分布式应用程序,为写入分布式应用程序提供服务。
zooKeeper提供的常见服务如下 :
-
命名服务 - 按名称标识集群中的节点。它类似于DNS,但仅对于节点。
-
配置管理 - 加入节点的最近的和最新的系统配置信息。
-
集群管理 - 实时地在集群和节点状态中加入/离开节点。
-
选举算法 - 选举一个节点作为协调目的的leader。
-
锁定和同步服务 - 在修改数据的同时锁定数据。此机制可帮助你在连接其他分布式应用程序(如Apache HBase)时进行自动故障恢复。
-
高度可靠的数据注册表 - 即使在一个或几个节点关闭时也可以获得数据。
分布式应用程序提供了很多好处,但它们也抛出了一些复杂和难以解决的挑战。ZooKeeper框架提供了一个完整的机制来克服所有的挑战。竞争条件和死锁使用故障安全同步方法进行处理。另一个主要缺点是数据的不一致性,ZooKeeper使用原子性解析。
zooKeeper的好处
以下是使用zooKeeper的好处:
- 简单的分布式协调过程
- 同步 - 服务器进程之间的相互排斥和协作。此过程有助于Apache HBase进行配置管理。
- 有序的消息
- 序列化 - 根据特定规则对数据进行编码。确保应用程序运行一致。这种方法可以在MapReduce中用来协调队列以执行运行的线程。
- 可靠性
- 原子性 - 数据转移完全成功或完全失败,但没有事务是部分的。
3. zookeeper 基础
zooKeeper的架构
作为ZooKeeper架构的一部分的每个组件在下表中进行了说明。
| 部分 | 描述 |
|---|---|
| Client(客户端) | 客户端,我们的分布式应用集群中的一个节点,从服务器访问信息。对于特定的时间间隔,每个客户端向服务器发送消息以使服务器知道客户端是活跃的。类似地,当客户端连接时,服务器发送确认码。如果连接的服务器没有响应,客户端会自动将消息重定向到另一个服务器。 |
| Server(服务器) | 服务器,我们的ZooKeeper总体中的一个节点,为客户端提供所有的服务。向客户端发送确认码以告知服务器是活跃的。 |
| Ensemble | ZooKeeper服务器组。形成ensemble所需的最小节点数为3。 |
| Leader | 服务器节点,如果任何连接的节点失败,则执行自动恢复。Leader在服务启动时被选举。 |
| Follower | 跟随leader指令的服务器节点。 |
层次命名空间
下图描述了用于内存表示的ZooKeeper文件系统的树结构。ZooKeeper节点称为 znode 。每个znode由一个名称标识,并用路径(/)序列分隔。
- 在图中,首先有一个由“/”分隔的znode。在根目录下,你有两个逻辑命名空间 config 和 workers 。
- config 命名空间用于集中式配置管理,workers 命名空间用于命名。
- 在 config 命名空间下,每个znode最多可存储1MB的数据。这与UNIX文件系统相类似,除了父znode也可以存储数据。这种结构的主要目的是存储同步数据并描述znode的元数据。此结构称为 ZooKeeper数据模型。
Znode兼具文件和目录两种特点。既像文件一样维护着数据长度、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分。每个Znode由三个部分组成:
- stat:此为状态信息,描述该Znode版本、权限等信息。
- data:与该Znode关联的数据
-
children:该Znode下的节点
- 版本号 - 每个znode都有版本号,这意味着每当与znode相关联的数据发生变化时,其对应的版本号也会增加。当多个zookeeper客户端尝试在同一znode上执行操作时,版本号的使用就很重要。
- 操作控制列表(ACL)- ACL基本上是访问znode的认证机制。它管理所有znode读取和写入操作。
- 时间戳 - 时间戳表示创建和修改znode所经过的时间。它通常以毫秒为单位。ZooKeeper从“事务ID"(zxid)标识znode的每个更改。Zxid 是唯一的,并且为每个事务保留时间,以便你可以轻松地确定从一个请求到另一个请求所经过的时间。
- 数据长度 - 存储在znode中的数据总量是数据长度。你最多可以存储1MB的数据。
Znode的类型
Znode被分为持久(persistent)节点,顺序(sequential)节点和临时(ephemeral)节点。
- 持久节点 - 即使在创建该特定znode的客户端断开连接后,持久节点仍然存在。默认情况下,除非另有说明,否则所有znode都是持久的。
- 临时节点 - 客户端活跃时,临时节点就是有效的。当客户端与ZooKeeper集合断开连接时,临时节点会自动删除。因此,只有临时节点不允许有子节点。如果临时节点被删除,则下一个合适的节点将填充其位置。临时节点在leader选举中起着重要作用。
- 顺序节点 - 顺序节点可以是持久的或临时的。当一个新的znode被创建为一个顺序节点时,ZooKeeper通过将10位的序列号附加到原始名称来设置znode的路径。例如,如果将具有路径 /myapp 的znode创建为顺序节点,则ZooKeeper会将路径更改为 /myapp0000000001 ,并将下一个序列号设置为0000000002。如果两个顺序节点是同时创建的,那么ZooKeeper不会对每个znode使用相同的数字。顺序节点在锁定和同步中起重要作用。
- 容器节点(3.6新增的):ZooKeeper具有容器节点的概念。容器节点是特殊用途的节点,可用于诸如集群中的leader,分布式锁等场景。当删除容器节点的最后一个子节点时,也就是容器节点没有子节点之后,该容器节点会在未来某个时间被服务器删除。
- TTL节点(3.6新增的):在创建持久化或者持久化有序节点时,可以把节点设置为TTL节点。并指定TTL的时间,单位为毫秒。如果接在在TTL时间内未修改且没有子代,该节点会在未来某个时间被服务器删除。该属性默认是禁用的,需要额外配置才能启用。
Sessions(会话)
会话对于ZooKeeper的操作非常重要。会话中的请求按FIFO顺序执行。一旦客户端连接到服务器,将建立会话并向客户端分配会话ID 。
客户端以特定的时间间隔发送心跳以保持会话有效。如果ZooKeeper集合在超过服务器开启时指定的期间(会话超时)都没有从客户端接收到心跳,则它会判定客户端死机。
会话超时通常以毫秒为单位。当会话由于任何原因结束时,在该会话期间创建的临时节点也会被删除。
Watches(监视)
监视是一种简单的机制,使客户端收到关于ZooKeeper集合中的更改的通知。客户端可以在读取特定znode时设置Watches。Watches会向注册的客户端发送任何znode(客户端注册表)更改的通知。
Znode更改是与znode相关的数据的修改或znode的子项中的更改。只触发一次watches。如果客户端想要再次通知,则必须通过另一个读取操作来完成。当连接会话过期时,客户端将与服务器断开连接,相关的watches也将被删除。
4. zookeeper 安装
4.1 单机安装
4.1.1 安装JDK
ZooKeeper服务器是用Java创建的,它在JVM上运行。你需要使用JDK 6或更高版本。linux安装jdk8
# 查看jdk版本
java -version
4.1.2 下载安装zookeeper
# 下载对应版本安装包
wget http://mirrors.bfsu.edu.cn/apache/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz
# 解压到指定安装目录
tar -zxvf apache-zookeeper-3.6.2-bin.tar.gz -C /usr/local/zookeeper
# 创建数据和日志目录
cd /usr/local/zookeeper && mv apache-zookeeper-3.6.2-bin apache-zookeeper-3.6.2
mkdir -pv data logs
# 设置自己的配置文件
vi /usr/local/zookeeper/apache-zookeeper-3.6.2/conf/zoo.cfg
4.1.3 zookeeper配置文件
# 心跳间隔 毫秒
tickTime=1000
# 启动时leader连接follower,超过多少次心跳间隔,follower连接超时
initLimit=10
# leader与follower 通信超时 最长心跳间隔次数
syncLimit=5
# 客户端连接的端口
clientPort=2181
# 客户端连接的最大数量
#maxClientCnxns=60
# 数据文件目录
dataDir=/usr/local/zookeeper/apache-zookeeper-3.6.2/data
# 日志目录
dataLogDir=/usr/local/zookeeper/apache-zookeeper-3.6.2/logs
# 最小会话超时时间
# minSessionTimeout=2000
# 最大会话超时时间
# maxSessionTimeout=20000
# 清除任务间隔(以小时为单位)
# 设置为0以禁用自动清除功能
autopurge.purgeInterval=5
# 最多保存20个文件 日志文件、快照
autopurge.snapRetainCount=20
#开启四字命令
#4lw.commands.whitelist=*
# 集群信息
# server.A=B:C:D
# A 代表记号服务器,在dataDir目录下myid文件下记录
# B 服务器ip地址
# C 服务器与集群中的leader服务器交换信息的端口
# D 选举leader所用的端口
# server.1=127.0.0.1:3181:4181
4.1.4 常用shell操作命令
- 启动zk : bin/zkServer.sh start
- 查看ZK服务状态: bin/zkServer.sh status
- 停止ZK服务: bin/zkServer.sh stop
- 重启ZK服务: bin/zkServer.sh restart
- 连接服务器 : bin/zkCli.sh -server 127.0.0.1:2181
4.1.5 启动并测试服务:
# 启动服务
./bin/zkServer.sh start
# 启动客户端测试
./bin/zkCli.sh
4.2 单机伪集群
使用一台服务器,创建多个服务实现zookeeper伪集群。
4.2.1 创建集群目录结构
这里创建clester目录,为每个服务指定目录。
data是数据目录,conf是配置文件目录,logs是日志目录。
# 创建每个服务对应的目录 这里使用2181,2182,2183三个端口
mkdir -pv cluster/{2181/{conf,data,logs},2182/{conf,data,logs},2183/{conf,data,logs}}
4.2.2 指定服务机器名称
zookeeper集群中的每台机器都知道其他的机器的信息,便于在集群出现问题后,重新选举leader等。
# 指定服务机器名称
echo 1 > cluster/2181/data/myid
echo 2 > cluster/2182/data/myid
echo 3 > cluster/2183/data/myid
4.2.3 创建服务配置文件
为每个服务配置指定的配置文件,主要修改端口号,数据、日志目录。
# 进入2181服务目录,修改其配置文件
vi cluster/2181/conf/zoo.cfg
# 更改端口号,数据、日志目录,并配置集群机器信息
clientPort=2181
dataDir=/usr/local/zookeeper/apache-zookeeper-3.6.2/cluster/2181/data
dataLogDir=/usr/local/zookeeper/apache-zookeeper-3.6.2/cluster/2181/logs
server.1=127.0.0.1:3181:4181
server.2=127.0.0.1:3182:4182
server.3=127.0.0.1:3183:4183
这里是单机伪集群,通信端口和选举端口都是不一样的,正式使用不用机器,可以是不同ip和统一端口号。
# 复制配置文件到其他服务目录
cp cluster/2181/conf/zoo.cfg cluster/2182/conf/zoo.cfg
cp cluster/2181/conf/zoo.cfg cluster/2183/conf/zoo.cfg
# 修改其他服务配置文件
vi cluster/2182/conf/zoo.cfg
vi cluster/2182/conf/zoo.cfg
# vim 快速替换 %s/2181/2182/g
4.2.4 启动集群服务
使用集群不同服务目录配置文件,启动对应服务。
./bin/zkServer.sh start /usr/local/zookeeper/apache-zookeeper-3.6.2/cluster/2181/conf/zoo.cfg
./bin/zkServer.sh start /usr/local/zookeeper/apache-zookeeper-3.6.2/cluster/2182/conf/zoo.cfg
./bin/zkServer.sh start /usr/local/zookeeper/apache-zookeeper-3.6.2/cluster/2183/conf/zoo.cfg
4.2.5 查看服务状态
./bin/zkServer.sh status /usr/local/zookeeper/apache-zookeeper-3.6.2/cluster/2181/conf/zoo.cfg
./bin/zkServer.sh status /usr/local/zookeeper/apache-zookeeper-3.6.2/cluster/2182/conf/zoo.cfg
./bin/zkServer.sh status /usr/local/zookeeper/apache-zookeeper-3.6.2/cluster/2183/conf/zoo.cfg
通过status可以查看服务的状态,我们启动三个服务,有一个leader和两个follower。
可以看到2182是leader,2181和2183是follower。
我们尝试把2182(leader)停止,再去查看状态,可以看到重新选举了2183为leader,2182重新启动后会成为follower。
5. zookeeper CLI
ZooKeeper命令行界面(CLI)用于与ZooKeeper集合进行交互以进行开发。它有助于调试和解决不同的选项。
要执行ZooKeeper CLI操作,首先打开ZooKeeper服务器(“bin/zkServer.sh start”),然后打开ZooKeeper客户端(“bin/zkCli.sh”)。
5.1 节点属性
| 属性名 | 属性说明 |
|---|---|
| cZxid | 数据节点创建的事务id |
| cZxid | 数据节点创建的事务id。 |
| ctime | 数据节点创建的时间。 |
| mZxid | 数据节点最后一次更新时的事务id |
| mtime | 数据节点最后一次更新的时间。 |
| pZxid | 数据节点的子节点最后一次被修改时的事务id。 |
| cversion | 子节点的更改次数。 |
| dataVersion | 节点数据的更改次数,也就是数据的版本。类似于关系型数据库的乐观锁。 |
| aclVersion | 节点ACL权限的更改次数。 |
| ephemeralOwner | 如果节点是临时节点,则该属性表示创建该节点的会话SessionId。如果该节点是持久节点,该属性为0,可以使用该属性来判断节点是否为临时节点。 |
| dataLength | 数据的内容长度,单位字节。 |
| numChildren | 子节点的个数。 |
zxid:致使ZooKeeper节点状态改变的每一个操作都将使节点接收到一个递增的事务id号,并且这个时间戳全局有序。也就是说,也就是说,每个对节点的改变都将产生一个唯一的Zxid。如果Zxid1的值小于Zxid2的值,那么Zxid1所对应的事件发生在Zxid2所对应的事件之前。实际上,ZooKeeper的每个节点维护者三个Zxid值,为别为:cZxid、mZxid、pZxid。
5.2 常用操作
介绍关于节点的常用操作,包括节点的增删改查,以及配额、同步等。
# 创建一个节点 -e为临时节点 -s为顺序节点 -c为容器节点 -t为ttl节点
create /file "file data"
# 获取当前节点数据
get /file
# 设置节点数据
set /file "data"
# 创建子节点
create /file/test "data"
# 获取当前节点状态
stat /file
# 删除一个节点
delete /file
# 删除指定版本的节点
delete -v 1 /file
# 删除节点以及其包含的子节点
deleteall /file
# 设置节点配置
# -n 子节点个数 -b 节点数据长度
# 超出配额并不会报错,而是会在日志(*.out)中出现警告
setquota /data -n 3
setquota /data -b 100
# 查看配额
listquota /data
# 删除配额
delquota /data
# 列出节点下面的所有子节点
ls -R /
# 强制同步所有的更新操作
sync /data
其他命令:
close:关闭当前连接
history:查看历史执行指令
redo命令
再次执行某命令。
如redo 10
其中10为命令ID,需与history配合使用。
sync
由于请求在半数以上的zk server上生效就表示此请求生效,那么就会有一些zk server上的数据是旧的。sync命令就是强制同步所有的更新操作。
printwatches
在获取节点数据、子节点列表等操作时,都可以添加watch参数监听节点的变化,从而节点数据更改、子节点列表变更时收到通知,并输出到控制台。默认是打开,可以设置参数将其关闭。
6. 运维四字命令
zookeeper可以通过它自身提供的简写命令来和服务器进行交互,需要使用到nc命令.
# 安装命令
yum install nc
在配置文件中开启四字命令
4lw.commands.whitelist=*
查看配置信息:
conf
conf命令用于输出 ZooKeeper服务器运行时使用的基本配置信息,包括clientPort、dataDir和tickTime等,以便运维人员能快速查看 ZooKeeper当前运行时的一些参数,如上图所示。注意,conf命令输出的配置信息仅仅是输出一些最基本的配置参数。
另外,conf命令会根据当前的运行模式来决定输出的信息。上图所示的输出信息是针对集群模式下的样例,如果是单机模式(standalone),就不会输出诸如initLimit、syncLimit、electionAlg和electionPort等集群相关的配置信息。
cons
cons命令用于输出当前这台服务器上所有客户端连接的详细信息,包括每个客户端的客户端IP、会话ID和最后一次与服务器交互的操作类型等。
crst
crst命令是一个功能性命令,用于重置所有的客户端连接统计消息
dump
dump命令用于输出当前集群的所有会话信息,包括这些会话的会话ID,以及每个会话创建的临时节点等信息。如果在Leader服务器上执行该命令的话,我们还能够看到每个会话的超时时间。
envi
envi命令用于输出 ZooKeeper所在服务器运行时的环境信息,包括os.version、java.version和user.home等。
ruok
ruok命令用于输出当前 ZooKeeper服务器是否正在运行。该命令的名字非常有趣,其协议正好是“Are you ok”。执行该命令后,如果当前 ZooKeeper服务器正在运行,那么返回“imok”,否则没有任何响应输出。
请注意,ruok命令的输出仅仅只能表明当前服务器是否正在运行,准确的讲,只能说明2181端口打开着,同时四字命令执行流程正常,但是不能代表 ZooKeeper服务器是否运行正常。在很多时候,如果当前服务器无法正常处理客户端的读写请求,甚至已经无法和集群中的其他机器进行通信,ruok命令依然返回“imok”。因此,一般来说,该命令并不是一个特别有用的命令,他不能反映 ZooKeeper服务器的工作状态,想要更可靠的获取更多 ZooKeeper运行状态信息,可以使用下面马上要讲到的stat命令。
stat
stat命令用于获取 ZooKeeper服务器的运行时状态信息,包括基本的 ZooKeeper版本、打包信息、运行时角色、集群数据节点个数等消息,另外还会将当前服务器的客户端连接信息打印出来。
除了一些基本的状态信息外,stat命令还会输出一些服务器的统计信息,包括延迟情况、收到请求数和返回的响应数等。注意,所有这些统计数据都可以通过srst命令进行重置。
srvr
srvr命令和stat命令的功能一致,唯一的区别是srvr不会将客户端的连接情况输出,仅仅输出服务器的自身信息
srst
stst命令是一个功能行命令,用于重置所有服务器的统计信息。
wchs
wchs命令用于输出当前服务器上管理的Watcher的概要信息。
wchc
wchc命令用于输出当前服务器上管理的Watcher的详细信息,以会话为单位进行归组,同时列出被该会话注册了Watcher的节点路径。
wchp**
wchp命令和wchc命令非常类似,也是用于输出当前服务器上管理的Watcher的详细信息,不同点在于wchp命令的输出信息以节点路径为单位进行归组。
mntr
mntr命令用于输出比stat命令更为详尽的服务器统计信息,包括请求处理的延迟情况,服务器内存数据库大小和集群的数据同步情况。在输出结果中,每一行都是一个key-value的键值对,运维人员可以,根据这些输出信息进行 ZooKeeper的运行时状态监控。
如果在Leader服务器上执行该命令的话,可以获取比Follower服务器更多的信息。
7. ACL权限
ACL全称为Access Control List(访问控制列表),用于控制资源的访问权限。ZooKeeper使用ACL来控制对其znode(ZooKeeper数据树的数据节点)的访问。ACL实现与UNIX文件访问权限非常相似:它使用权限位来允许/禁止针对节点的各种操作以及位应用的范围。与标准UNIX权限不同,ZooKeeper节点不受用户(文件所有者),组和world(其他)的三个标准范围的限制。
zk利用ACL策略控制节点的访问权限,如节点数据读写、节点创建、节点删除、读取子节点列表、设置节点权限等。
在传统的文件系统中,一个文件拥有某个组的权限即拥有了组里的所有权限,文件或子目录默认会继承自父目录的ACL。而在Zookeeper中,znode的ACL是没有继承关系的,每个znode的权限都是独立控制的,只有客户端满足znode设置的权限要求时,才能完成相应的操作。
Zookeeper的ACL,分为三个维度:scheme、id、permission,通常表示为:scheme