ZooKeeper 学习笔记

一、简介

zooKeeper是一个经典的分布式数据一致性解决方案服务,致力于为分布式应用提供一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调存储服务。zooKeeper由雅虎研究院开发,是Google Chubby的开源实现,后来托管到Apache,于2010年11月正式成为Apache的顶级项目。

zookeeper官网:https://zookeeper.apache.org/

二、应用场景

(1)维护配置信息
(2)分布式锁服务
(3)集群管理
(4)生成分布式唯一ID

三、数据模型

zookeeper的数据节点可以视为树状结构(或者文件系统),树中的各节点被称为znode(即zookeeper node),一个znode可以有多个子节点。zookeeper节点在结构上表现为树状;使用路径path来定位某个znode。znode兼具文件和目录(文件路径而非文件夹)两种特点,既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分。

image-20210110205356642

一个znode大体上分为3各部分:

  • data:与该Znode关联的数据,即znode data(节点path, 节点data)的关系就像是java map中(key,value)的关系

  • children:该Znode下的子节点

  • stat:该Znode节点的状态信息,用来描述当前节点的创建、修改记录、版本、权限等、包括cZxid、ctime等

    cZxid 数据节点创建时的事务 ID
    ctime 数据节点创建时的时间
    mZxid 数据节点最后一次更新时的事务 ID
    mtime 数据节点最后一次更新时的时间
    pZxid 数据节点的子节点最后一次被修改时的事务 ID
    cversion 子节点的更改次数
    dataVersion 节点数据的更改次数
    aclVersion 结点的ACL更改次数——类似linux的权限列表,维护的是当前结点的权限列表被修改的次数
    ephemeralOwner 如果节点是临时节点,则表示创建该节点的会话的SessionID;如果节点是持久节点,则该属性值为 0
    dataLength 数据内容的长度
    numChildren 数据节点当前的子节点个数

Znode的类型

Znode被分为持久(persistent)节点,顺序(sequential)节点和临时(ephemeral)节点。

  • 持久节点 - 该结点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,它们才能被删除

  • 临时节点 - 该节点的生命周期依赖于创建它们的会话。一旦会话( Session)结束,临时节点将被自动删除,当然可以也可以手动删除。虽然每个临时的 Znode都会绑定到一个客户端会话,但他们对所有的客户端还是可见的。另外,Zookeeper的临时节点不允许拥有子节点

  • 顺序节点 - 顺序节点可以是持久的或临时的。当一个新的znode被创建为一个顺序节点时,ZooKeeper通过将10位的序列号附加到原始名称来设置znode的路径。例如,如果将具有路径 /myapp 的znode创建为顺序节点,则ZooKeeper会将路径更改为 /myapp0000000001 ,而下一个序列号将递增为0000000002。顺序节点在锁定和同步中起重要作用。

四、安装部署

1. 单机版

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
$ mkdir /opt/zookeeper
$ cd /opt/zookeeper
$ wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
$ tar -zxvf zookeeper-3.4.14.tar.gz
$ mkdir /opt/zookeeper/zookeeper-3.4.14/data
$ cd zookeeper-3.4.14/conf
$ cp zoo_sample.cfg zoo.cfg

$ vim zoo.cfg
#此路径用于存储zookeeper中数据的内存快照、及事务日志文件,虽然zookeeper是使用内存的,但是需要持久化一些数据来保证数据的安全
dataDir=/opt/zookeeper/zookeeper-3.4.14/data

$ cd /opt/zookeeper/zookeeper-3.4.14/bin/

#启动zookeeper
$ zkServer.sh start

# 启动
$ zkServer.sh start
# 重启
$ zkServer.sh restart
# 停止
$ zkServer.sh stop
# 查看状态
$ zkServer.sh status

# zookeeper客户端命令工具连接到zookeeper服务
$ zkCli.sh

2. docker版

1
2
3
$ docker run -d --name zookeeper --restart always -e JVMFLAGS="-Xmx1024m" -p 2181:2181 zookeeper
$ docker exec -it zookeeper /bin/bash
$ /apache-zookeeper-3.6.2-bin/bin/zkCli.sh

3. 集群

3.1 架构

看看下面的图表。它描述了ZooKeeper的“客户端-服务器架构”。

image-20220807152858402

图中部分组件在下表中进行了说明。

部分 描述
Client 客户端,我们的分布式应用集群中的一个节点,从服务器访问信息。对于特定的时间间隔,每个客户端向服务器发送消息以使服务器知道客户端是活跃的。类似地,当客户端连接时,服务器发送确认码。如果连接的服务器没有响应,客户端会自动将消息重定向到另一个服务器。
Server 服务器,我们的ZooKeeper总体中的一个节点,为客户端提供所有的服务。向客户端发送确认码以告知服务器是活跃的。
Leader 服务领导者。1、处理事务请求和非事务请求(如增删改查);2、调度集群内部的各个服务
Follower 服务跟随者。1、处理非事务请求(如查,如果接收到事务请求的话则转发给Leader);2、参与Leader选举投票
Observer 服务观察者。1、处理非事务请求(如查,如果接收到事务请求的话则转发给Leader)。(不参与Leader选举投票)

3.2 部署

准备三台服务器(多台同理,需要基数倍,集群中从3台变成2台仍可用,而变成1台时将不不可用)

172.16.10.111
172.16.10.112
172.16.10.113

分别在三台zk服务器中执行如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ mkdir -p /home/zookeeper/conf
$ mkdir -p /home/zookeeper/data

$ vim /home/zookeeper/conf/zoo.cfg
clientPort=2181
dataDir=/data
dataLogDir=/data/log
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
server.111=172.16.10.111:2888:3888
server.112=172.16.10.112:2888:3888
server.113=172.16.10.113:2888:3888

#想让服务节点为observer观察者,需要如下两行配置
#peerType=observer
#server.113=172.16.10.113:2888:3888:observer

server.服务id=服务器ip:服务器之间通信端口:服务之间投票选举端口
服务id编号越大,在Leader选举中权重越大,选举票数超过半数则为Leader。

分别在三台zk服务器中的/home/zookeeper/data目录下创建myid,并配置id,里面的id一定要和上面配置的server.id一致

1
2
3
4
5
6
#zk1
$ echo 111 > /home/zookeeper/data/myid
#zk2
$ echo 112 > /home/zookeeper/data/myid
#zk3
$ echo 113 > /home/zookeeper/data/myid

分别运行zk docker镜像

1
2
3
4
5
6
7
8
9
10
11
#获取zk docker镜像
$ docker pull zookeeper:3.4.13
#运行镜像生产docker容器

$ docker run --network host -v /home/zookeeper/data:/data -v /home/zookeeper/conf:/conf --name zookeeper-2181 -d zookeeper:3.4.13
#或者以下(目前发现以下命令不可用)
#docker run -d -p 2181:2181 -p 2888:2888 -p 3888:3888 --restart=always -v /home/zookeeper/data:/data -v /home/zookeeper/conf:/conf --name=zookeeper-2181 zookeeper:3.4.13

#进入容器中查看leader选举情况
$ docker exec -it zookeeper-2181 /bin/sh
$ zkServer.sh status

每台主机的2181/2888/3888端口都会开放出来

1
2
3
4
5
6
$ service firewalld start
$ firewall-cmd --permanent --add-port=2181/tcp
$ firewall-cmd --permanent --add-port=2888/tcp
$ firewall-cmd --permanent --add-port=3888/tcp
$ firewall-cmd --reload
$ firewall-cmd --list-all

五、常用命令

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
##1、查看目录列表(子节点列表)
#查看某个路径下目录列表
#path:指定要创建节点的路径,比如 /test
ls path
#查看某个路径下目录列表,它比 ls 命令列出更多的详细信息
ls -s path
ls2 path #旧版

##2、获取节点数据和状态信息
#(1)获取节点数据和状态信息,[watch]:对节点进行事件监听。
get path [watch]
#例:
get /test watch #终端1查询并监听节点
set /test 1 #终端2对节点进行修改

#(2)查看节点状态信息
stat path [watch]


##3、创建节点并赋值
#[-s] [-e]:-s 和 -e 都是可选的,-s 代表顺序节点(递增), -e 代表临时节点(不加表示持久节点),注意其中 -s 和 -e 可以同时使用的,并且临时节点不能再创建子节点。
#path:指定要创建节点的路径,比如 /test
#data:要在此节点存储的数据。不设置则为null
#acl:访问权限相关,默认是 world,相当于全世界都能访问。
create [-s] [-e] path [data] [acl]
#例:添加临时顺序节点并赋值
create -s -e /test "hello"

##4、修改节点存储的数据
#[version]:可选项,版本号(可用作乐观锁)。即状态信息中的dataVersion
set path data [version]


##5、删除节点
#[version]:可选项,版本号(同 set 命令)。
#delete 命令只能一层一层删除。新版本可以通过 deleteall 命令递归删除
delete path [version]

六 、权限控制

zookeeper 的 ACL(Access Control List,访问控制表)权限可以针对节点设置相关读写等权限,保障数据安全性。

zookeeper 的 acl 通过 [scheme:id:permissions] 来构成权限列表。

  • (1)scheme:代表采用的某种权限机制(权限模式),包括 world、auth、digest、ip、super 几种。

    world:只有一个用户:anyone,代表登录zookeeper所有人(默认)

    auth:使用已添加认证的用户认证

    digest:使用"用户名:密码"方式认证

    ip:限制ip进行访问

  • (2)id:代表允许访问的用户。
  • (3)permissions:权限组合字符串,由 cdrwa 组成,其中每个字母代表支持不同权限,

    create©:创建子节点权限

    delete(d):删除子节点的权限

    read®:获取当前节点/子节点的权限

    write(w):设置节点数据的权限

    admin(a):设置节点权限的权限。

1. world模式

1
2
3
4
5
6
7
8
9
10
11
$ create /test
$ create /test/child
$ getAcl /test
#更新节点 permissions 权限部分为 crwa
$ setAcl /test world:anyone:crwa
#结果删除子节点失败
$ delete /test/child
#更新节点 permissions 权限部分为 cdrwa
$ setAcl /test world:anyone:cdrwa
#结果删除子节点成功
$ delete /test/child

2. auth模式

auth 用于授予权限(以用户名和明文密码的形式授权)。

1
2
3
4
5
6
7
$ create /test/child demo
#给当前会话创建用户名为user1密码为123456的用户
$ addauth digest user1:123456
$ setAcl /test/child auth:user1:123456:cdrwa
$ getAcl /test/child
'digest,'user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=
: cdrwa

另外起一个终端测试

1
2
3
4
5
6
7
8
$ get /test/child
#提示如下无权限操作
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test/child

#给当前会话创建该节点需要的用户后就可以操作节点了
$ addauth digest user1:123456
#在=再次操作即可成功
$ get /test/child

3. digest模式

digest同样用于授予权限(以用户名和密文密码的形式授权,密文可在创建时的会话中通过getAcl查看)。

1
2
3
4
5
6
7
# 计算密码
echo -n user1:123456 | openssl dgst -binary -sha1 | openssl base64
# 获取密码,设置权限列表
setAcl /test2 digest:user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=:cdrwa
# 现在想要get /hadoop 需要登录了
addauth digest user1:123456
get /test2

4. ip模式

限制 IP 地址的访问权限,把权限设置给 IP 地址为 192.168.3.7 后,IP 为 192.168.3.38 已经没有访问权限。

1
2
3
4
5
6
$ create /test/ip 0
$ getAcl /test/ip
$ setAcl /test/ip ip:192.168.3.7:cdrwa
$ get /test/ip
#假设当前所在终端并非192.168.3.7,则提示无权限操作
Authentication is not valid : /test/ip

5. 组合模式

仅需逗号隔开

  • 1
    setAcl /test ip:192.168.3.7:cdrwa,auth:user1:cdrwa,digest:user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=:cdrwa

6. 超级管理员

zookeeper的权限管理模式有一种叫做super,该模式提供一个超管,可以方便的访问任何权限的节点。

默认是没有配置super的,需要到zookeeper目录下/bin/zkServer.sh文件中加相关配置。

1
2
/nohup # 快速查找,可以看到如下
nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \

加入运行参数-Dzookeeper.DigestAuthenticationProvider.superDigest。如下:

1
nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs=" \

注意:-Dzookeeper.DigestAuthenticationProvider.superDigest参数的值为super:密码摘要。假设密码为admin,可通过如下获得密码摘要。

1
echo -n super:admin | openssl dgst -binary -sha1 | openssl base64

如果使用的是docker安装的,可以在运行容器的时候指定jvm参数如下设置超级管理员即可(不需要修改zkServer.sh)。

1
docker run -d --name zookeeper --restart always -e JVMFLAGS="-Xmx1024m -Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs=" -p 2181:2181 zookeeper

使用

1
2
3
4
# 登录超管
addauth digest super:admin
# 强行操作节点(设/test/ip节点在登录前无权操作)
get /test/ip

七、图形化客户端

1. PrettyZoo

下载地址:https://github.com/vran-dev/PrettyZoo/releases

2. ZooInspector

下载地址:https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip

  • 解压后进入目录ZooInspector\build,运行java -jar zookeeper-dev-ZooInspector.jar


----------- 本文结束 -----------




如果你觉得我的文章对你有帮助,你可以打赏我哦~
0%