目录
一、什么是ZooKeeper
Zookeeper 是一个开源的分布式协调服务【Google Chubby的开源实现】。ZooKeeper 可以用于实现分布式系统中常见的发布/订阅、负载均衡、命令服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
1.1 ZooKeeper的特点
-
顺序一致性 :来自客户端的更新将按发送顺序应用。
-
原子性:更新成功或失败。无部分结果。
-
单个系统映像:客户端将看到相同的服务视图,无论它连接到哪个服务器。即,即使客户端故障转移到具有相同会话的不同服务器,客户端也永远不会看到系统的旧视图。
-
可靠性:应用更新后,它将从那时起一直存在,直到客户端覆盖更新。
-
及时性:保证系统的客户端视图在特定时间范围内是最新的。
1.2 ZooKeeper架构
ServerCnxnFactory:向外暴露TCP长链接,维护双向链接通道,分发请求。
LearnerCnxAcceptor:Leader服务Socket服务端,接收Follower、Observer服务的创建链接请求,创建LearnerHandler,用于内部数据交互。
FastLeaderElection:Leader内部选举,为避免双方重复创建链接,由myid
大的向myid
小的创建链接
SessionTracker:会话管理及独立线程会话超时清理
ZKDatabase:ZooKeeper的内存数据库,负责管理DataTree、事务日志,启动时从事务日志和快照中恢复到该内存数据库,运行期,将接收到的事务请求写入事务日志,当触发快照操作时,提供数据。
1.3 ZooKeeper数据模型
ZooKeeper 的数据节点可以视为树状结构,树中的各节点被称为 Znode,一个 Znode 可以有多个子节点,ZooKeeper 中的所有存储的数据是由 znode 组成,并以 key/value 形式存储数据。整体结构类似于 linux 文件系统的模式以树形结构存储,其中根路径以 / 开头
1.4 数据节点类型
-
持久节点【PERSISTENT】:数据节点被创建后,就会一直存在ZooKeeper服务器上,直到有删除操作主动清除节点数据。
-
持久顺序节点【PERSISTENT_SEQUENTIAL】:在持久性的基础上,又具有了顺序性特性。每个父节点都会为它的第一级子节点维护一份顺序,用于记录每个子节点的先后顺序。在创建子节点过程中,ZooKeeper会自动为给定的节点名加上一个数字后缀。
-
临时节点【EPHEMERAL】:临时节点的生命周期和客户端的会话绑定在一起,如果客户端会话失效,该会话对应的临时节点就会被自动清理。临时节点不能创建子节点。
-
临时顺序节点【EPHEMERAL_SEQUENTIAL】:在临时节点的特性上,添加了顺序性特点。
二、Zookeeper安装
2.1 单机安装
-
安装JDK环境并配置环境变量
JAVA_HOME
-
下载ZooKeeper软件
# mkdir -p /opt/soft/zookeeper/
# wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.2/apache-zookeeper-3.8.2-bin.tar.gz
# tar -xvzf apache-zookeeper-3.8.2-bin.tar.gz
-
配置相关调整
// 创建事务日志和快照目录
# mkdir -p /data/zk/data
# mkdir -p /data/zk/log
//复制并修改配置信息
# cp -r /opt/soft/zookeeper/apache-zookeeper-3.8.2-bin/conf/zoo_sample.cfg /opt/soft/zookeeper/apache-zookeeper-3.8.2-bin/conf/zoo.cfg
#vi /opt/soft/zookeeper/apache-zookeeper-3.8.2-bin/conf/zoo.cfg
//修改快照路径并新增事务日志目录
dataDir=/data/zk/data
dataLogDir=/data/zk/log
-
服务启动
# /opt/soft/zookeeper/apache-zookeeper-3.8.2-bin/bin/zkServer.sh start
2.2 集群安装
集群安装相比单机安装,需要在配置中维护节点的角色是参与者或观察者【默认角色为参与者】和集群节点的各个成员,3.5.0开始可用通过动态配置完成集成成员的维护
-
zoo.cfg配置调整为动态配置
## 去除clientPort,改为动态配置
##clientPort=2181
## 跳过acl检查。如果不设置成yes,则需要superuser权限才能执行reconfig
skipACL=yes
## 开启动态配置
reconfigEnabled=true
## 加载dynamic配置文件的路径
dynamicConfigFile=/conf/zoo.cfg.dynamic
-
初始化集群成员配置
## zoo1\zoo2\zoo3为各节点地址,2888为LF交互端口,3888为Leader选举端口,2181为向客户端暴漏端口,各地址对应端口火墙互通
server.1=zoo1:2888:3888;2181
server.2=zoo2:2888:3888;2181
server.3=zoo3:2888:3888;2181
-
各个节点设置myid文件
// 每个节点设置的不同,例如zoo1设置为1
# echo '1' > /data/zk/data/myid
-
启动各个节点服务,并检测配置
# ${ZK_HOME}/bin/zkCli.sh
//查看维护的节点配置
> config
server.1=zoo1:2888:3888:participant;0.0.0.0:2181
server.2=zoo2:2888:3888:participant;0.0.0.0:2181
server.3=zoo3:2888:3888:participant;0.0.0.0:2181
//动态添加4节点
> reconfig -add 4=zoo4:2888:3888;2181
//动态删除1节点
> reconfig -remove 1
-
执行reconfig命令后,需确认扩容/缩容是否成功:执行reconfig命令只意味着激活新配置的请求已发出,至于新配置有没有在所有节点上生效需要用户自行确认
-
应当尽量避免执行reconfig -remove leader节点,防止集群短暂不可用
-
zk客户端可通过监听zk路径:/zookeeper/config实时监听zk节点列表的变化(前提是:客户端配置的zk节点列表中至少一个可用)。得到完整的zk节点列表之后,zk客户端可平衡每个zk节点的请求数,客户端也无需重新配置zk节点列表甚至重启
ZooKeeper CLI使用
//启动zk客户端
# ${ZK_HOME}/bin/zkCli.sh
//查看客户端支持的命令
#help
//创建持久节点
# create /persistent_node
//创建持久顺序节点
# create -s /persistent_sequential_node mydata
//创建临时节点
# create -e /ephemeral_node mydata
//创建临时顺序节点
# create -s -e /ephemeral_sequential_node mydata
2.3 ZooKeeper ACL使用
为避免存储到节点的数据误修改或删除,ZooKeeper提供了ACL进行权限控制。
权限组成
Zookeeper 的权限由[scheme : id :permissions]三部分组成
Permissions 内置可选线:
-
CREATE:允许创建子节点
-
READ:允许从节点获取数据并列出其子节点
-
WRITE:允许为节点设置数据
-
DELETE:允许删除子节点
-
ADMIN:允许为节点设置权限
Schemes 内置可选项:
-
world:默认模式,所有客户端都拥有指定的权限。world下只有一个id选项anyone,通常组合写法为 world:anyone:[permissons]
-
auth:只有经过认证的用户才拥有指定的权限。通常写法为 auth:user:password:[permissons],使用这种模式时,你需要先进行登录,之后采用auth模式设置权限时,user和password都将使用登录的用户名和密码
-
digest:只有经过认证的用户才拥有指定的权限。通常写法为 auth:user:BASE64(SHA1(password)):[permissons],这种形式下的密码必须通过SHA1和BASE64进行双重加密
-
ip:限制只有特定IP的客户端才拥有指定的权限。通常写法为 ip:127.0.0.1:[permissions]
-
super:代表超级管理员,拥有所有的权限,通过启动参数
-Dzookeeper.DigestAuthenticationProvider.superDigest
设置用户名和密码
2.4 ZooKeeper使用场景
ZooKeeper使用场景如:集群管理、Master 选举、分布式锁和分布式队列等功能,如下介绍两种场景分布式锁和分布式原子操作
分布式锁: 基于临时节点的顺序性和监听机制实现,首次基于锁节点创建临时顺序节点时,由于锁节点下无临时节点,则该线程持有锁成功,其他线程抢占锁时,创建临时顺序节点,并查询该锁节点下的临时节点是否有大于该临时节点的节点,如果存在则添加离该临时节点最近的上一个节点添加监听事件,等待监听事件触发获取锁。锁的重入性由持有锁的应用内存实现
分布式原子操作: 基于节点的版本号实现,如果节点不存在则创建节点,之后操作时先查询节点数据,基于查询到的版本号更新该节点数据,更新失败,则查询节点数据重新计算新值基于新的版本号更新
2.5 服务启动流程
2.5.1 单机启动
-
统一由QuorumPeerMain作为启动类。无论是单机版还是集群模式启动服务,入口都是该类。
-
解析配置文件zoo.cfg。Zookeeper首先会进行配置文件的解析,配置文件的解析其实就是对zoo.cfg文件的解析。
<