ZooKeeper
ZooKeeper 由java开发
- 简介:Apache ZooKeeper 是一种用于分布式应用程序的高性能协调服务,提供一种集中式信息存储服务。
- 特点:数据存储在内存中,类文件系统的树形结构(文件和目录),高吞吐量和低延迟,集群高可靠。
- 作用:基于 ZooKeeper可以实现分布式统一配置中心、服务注册中心,分布式锁等功能。
- 发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列
Zookeeper Service
数据存储
ZooKeeper为C/S应用
分布式协调服务
- 单机系统因处理能力上限、可用性、可靠性的考虑,变成分布式系统。
- 原来在单机进程中完成一件事的多个步骤,变为在多个计算机中执行,这时就需要协调多个计算机节点做事的顺序,原来在单系统中资源竞争通过锁进行同步控制,现在变为多个计算机上的进程间资源竞争,也需要分布式协调。
- 我们可以把每个分布式系统中需要的协调管理的公共基础部分抽取出来作为一个基础公共服务供大家使用,这就是分布式协调服务。
应用案例
- Hbase:使用 ZooKeeper 进行 master 选举、服务间协调。
- Solr:使用 ZooKeeper 进行集群管理、Leader 选举、配置管理。
- dubbo:服务注册。
- Mycat:集群管理、配置管理。
- Sharding-JDBC:集群管理、配置管理。
同类产品
- consul、etcd(轻量级)、Doozer
单机版安装
-
解压后的 conf 目录,增加配置文件 zoo.cfg
配置参数:https://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_configuration
启动服务端:
bin/zkServer.sh start
客户端连接
zkCli.sh -server 127.0.0.1:2181`
服务端状态
sundeMacBook-Pro:~ sun$ zkServer status
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone
CLI-操作指令
指令 | 描述 |
---|---|
ls | 获取子节点。 |
create | 在 ZooKeeper 中的某个位置创建一个节点。 |
delete | 删除节点。 |
exists | 测试节点是否存在。 |
get data | 从指定节点读取数据。 |
set data | 将数据存入指定节点。 |
get children | c查询指定节点之下所有的子节点。 |
sync | 等待数据进行同步。 |
# 指令语法参照
ZooKeeper -server host:port -client-configuration properties-file cmd args
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path [-b batch size]
delquota [-n|-b] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b val path
stat [-w] path
sync path
version
Java API
- org.apache.zookeeper
- org.apache.zookeeper.data
- 创建客户端的核心类:Zookeeper
方法 | 描述 |
---|---|
connect | 连接到 ZooKeeper 集合 |
create | 创建 znode |
exists | 检查 znode 是否存在及其信息 |
get data | 从特定的 znode 获取数据 |
set data | 在特定的 znode 中设置数据 |
get children | 获取特定的 znode 中的所有子节点 |
delete | 删除指定的 znode 及其所有子项 |
close | 关闭连接 |
第三方客户端
java
zkClient
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>
curator
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
</dependency>
zookeeper
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.8</version>
</dependency>
PHP
参考://www.greatytc.com/p/82e0925ed37f
核心概念
session
- 一个客户端连接一个会话,由 zk 分配唯一会话 id;
- 客户端以特定的时间间隔发送心跳以保持会话有效:tickTime;
- 超过会话超时时间未收到客户端的心跳,则判定客户端死了;(默认 2 倍 tickTime)
- 会话中的请求按 FIFO 顺序执行。
数据模型
层次空间名称
- 类似 unix 文件系统,以(/)为根。
- 区别:节点可以包含与之关联的数据以及子节点(既是文件也是文件夹)。
- 节点的路径总是表示为规范的、绝对的、斜杠分隔的路径。
znode
- 名称唯一,命名规范。
- 节点类型:持久、顺序、临时、临时顺序。
- 节点数据构成
znode-命名规范
节点名称除以下限制外,可以使用任何 unicode 字符。
null 字符(\u0000)不能作为路径名的一部分;
以下字符不能使用,因为它们不能很好地显示,或者以令人困惑的方式呈现:\u0001-\u0019 和 \u007F-\u009F。
不允许使用以下字符:\ud800-\uf8ff,\uFFF0-\uFFFF。
“.” 字符可以用作另一个名称的一部分,但是 “.” 和 “..” 不能单独用于指示路径上的节点,因为 ZooKeeper 不适用相对路径。
下列内容无效:“/a/b/./c” 或 “c/a/b/../”
“zookeeper” 是保留节点名。
znode-节点类型
持久节点 -
create /app1 666
临时节点 -
create -e /app2 888
-
顺序节点
create -s /app1/cp 888
- cp0000000000create -s /app1/ aa
- 0000000001- 10 位十进制序号。
- 每个父节点一个计数器。
- 计数器是带符号 int(4 字节)到 2147483647 之后将溢出(导致名称“<path>-2147483648”)是一个负数
临时顺序节点 -
create -e -s /app1/ 888
(会话结束删除)
znode-数据构成
- 节点数据:存储的协调数据(状态信息、配置、位置信息等)。
- 节点元数据(stat 结构)。
- 数据量上限:1 M。
znode-元数据 stat 结构
zxid:事务ID
[zk: localhost:2181(CONNECTED) 21] get -s /zk_test
888
cZxid = 0x4600000009
ctime = Fri May 21 15:37:20 CST 2021
mZxid = 0x4600000009
mtime = Fri May 21 15:37:20 CST 2021
pZxid = 0x4600000009
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
Stat 结构字段 | 描述 |
---|---|
cZxid | 创建该节点的 zxid(事务 id) |
mZxid | 最后修改该节点的 zxid |
pZxid | znode 最后更新的子节点 zxid |
ctime | 该节点的创建时间 |
mtime | 该节点的最后修改时间 |
dataVersion | 该节点数据被修改的次数 |
cversion | 该节点的子节点变更次数 |
ephemeralOwner | 临时节点的所有者会话 id,如果不是临时节点,则为 0 |
dataLength | 该节点的数据的长度 |
numChildren | 子节点数 |
aclVersion | 访问控制列表变更次数 |
Zookeeper 中的时间
多种方式跟踪时间:
- zxid:ZooKeeper 中的每次更改操作都对应一个唯一的事物 id,称为 Zxid,它是一个全局有序的戳记,如果 zxid1 小于 zxid2,则zxid1 发生在 zxid2 之前。
- version numbers:版本号,对节点的每次更改都会导致该节点的版本号增加。
- ticks:当使用多服务器 ZooKeeper 时,服务器使用“滴答”来定义事件的时间,如状态上传、会话超时、对等点之间的连接超时等。滴答时间仅通过最小会话超时(滴答时间的 2 倍)间接公开;如果客户端请求的会话超时小于最小会话超时,服务器将告诉客户端会话超时实际上是最小会话超时。(基本时间单位)
- real time:ZooKeeper 除了在 znode 创建和修改时将时间戳放入 stat 结构之外,根本不使用 real time 或时钟时间。
访问控制
设置访问控制列表:https://zookeeper.apache.org/doc/current/zookeeperProgrammers.html#sc_ZooKeeperAccessControl
zookeeper ACL权限控制,使用scheme:id:perm
来标识
-
权限模式(scheme):授权的策略
- world:默认方式,相当于全部都能访问
- auth:代表已经认证通过的用户(cli中可以通过addauth digest user:pwd 来添加当前上下文中的授权用户)
- digest:即用户名:密码这种方式认证,这也是业务系统中最常用的。
- 用 username:password 字符串来产生一个MD5串,然后该串被用来作为ACL ID。
- 认证是通过明文发送username:password 来进行的,当用在ACL时,表达式为username:base64 ,base64是password的SHA1摘要的编码
- ip:使用客户端的主机IP作为ACL ID 。这个ACL表达式的格式为addr/bits ,此时addr中的有效位与客户端addr中的有效位进行比对。
-
授权对象(id):授权对象
授权对象ID是指,权限赋予的用户或者一个实体,例如:IP 地址或者机器。授权模式 schema 与 授权对象 ID 之间对应关系如下
- IP:ip地址或ip地址段,192.168.0.1 或 192.168.0.1/24
- Digest:自定义,通常是 "username:BASE64(SHA-1(username:password))
- World:只有一个ID anyone
- Super:与digest模式一致
-
权限(permission):授予的权限
CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、删、改、查、管理权限,这5种权限简写为crwda
注意:这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限。更详细的如下:
CREATE c 可以创建子节点
DELETE d 可以删除子节点(仅下一级节点)
READ r 可以读取节点数据及显示子节点列表
WRITE w 可以设置节点数据
ADMIN a 可以设置节点访问控制列表权限
- ACL 相关命令
- getAcl getAcl <path> 读取ACL权限
- setAcl setAcl <path> <acl> 设置ACL权限- addauth addauth <scheme> <auth> 添加认证用户
ZooKeeper的权限控制是基于每个znode节点的,需要对每个节点设置权限,每个znode支持设置多种权限控制方案和多个权限,子节点不会继承父节点的权限,客户端无权访问某节点,但可能可以访问它的子节点。
# 获取权限
[zk: localhost:2181(CONNECTED) 22] getAcl /zk_test
'world,'anyone
: cdrwa
# 设置权限
[zk: localhost:2181(CONNECTED) 23] setAcl /zk_test world:anyone:drwa
[zk: localhost:2181(CONNECTED) 24] getAcl /zk_test
'world,'anyone
: drwa
# 创建节点设置权限
[zk: localhost:2181(CONNECTED) 38] create -c /acl_test 123 world:anyone:drca
Created /acl_test
[zk: localhost:2181(CONNECTED) 39] getAcl /acl_test
'world,'anyone
: cdra
Watch 监听机制
客户端可以在 znodes 上设置 watch,监听 znode 的变化。
比如,客户端可以发送watch
命令,监听指定节点/app1/p_1
的动态
# 涉及watch的cli命令
config [-c] [-w] [-s]
get [-s] [-w] path
ls [-s] [-w] [-R] path
stat [-w] path
# 比如通过 get 监听 /a
[zk: localhost:2181(CONNECTED) 50] get /a -w
# watch 对应API
getData()
getChildren()
exists()
两类 watch
- data watch:监听数据变化
- child watch:监听子节点变化
触发 watch 事件
- Created event: Enabled with a call to
exists
. - Deleted event: enabled with a call to
exists
,getData
, andgetChildren
. - Changed event: Enabled with a call to
exists
andgetData
. - Child event: Enabled with a call to
getChildren
.
watch 重要特性
- 一次性触发:watch 触发后即被删除,要持续监控变化,则需要持续设置 watch。
- 有序性:客户端先得到 watch 通知,后才会看到变化结果。
watch 注意事项
- watch 是一次性触发器,如果你获得了一个 watch 事件,并且希望得到关于未来更改的通知,则必须设置另一个 watch。
- 因为 watch 是一次性触发器,并且在获取事件和发送获取 watch 的新请求之间存在延迟,所以不能可靠地得到节点发生的每个更改。
- 一个 watch 对象只会被特定的通知触发一次。如果一个 watch 对象同时注册了 exists、getData,当节点被删除时,删除事件对 exists、getData 都有效,但只会调用 watch 一次。
Zookeeper 特性
- 顺序一致性(Sequential Consistency):保证客户端操作是按顺序生效的。
- 原子性(Atomicity):更新成功或失败,没有部分结果。
- 单个系统映像:无论连接哪个服务器,客户端都将看到相同的内容。
- 可靠性:数据的变更不会丢失,除非被客户端覆盖修改。
- 及时性:保证系统的客户端当时读取到的数据是最新的。