ZooKeeper使用指南
1.ZooKeeper安装(3.6.3版本为例)
-
官网下载:https://zookeeper.apache.org/releases.html
-
下载完成后解压
tar -zxvf apache-zookeeper-3.6.3-bin.tar.gz
-
解压后进入到conf目录下
-
更改zoo_sample.cfg文件名为zoo.cfg文件名
mv zoo_sample.cfg zoo.cfg
-
zoo.cfg文件部分配置说明
tickTime=2000 dataDir=/opt/zookeeper/data clientPort=2181 #tickTime:ZooKeeper 使用的基本时间单位,以毫秒为单位。它用于进行心跳,最小会话超时将是tickTime 的两倍。 #dataDir:存储内存数据库快照的位置,除非另有说明,否则存储数据库更新的事务日志。 #clientPort : 监听客户端连接的端口
-
启动ZooKeeper服务
bin/zkServer.sh start
-
启动ZooKeeper客户端,连接到ZooKeeper
bin/zkCli.sh -server 127.0.0.1:2181
-
连接后,会看到如下内容:
Connecting to localhost:2181 log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper). log4j:WARN Please initialize the log4j system properly. Welcome to ZooKeeper! JLine support is enabled [zkshell: 0]
-
在 shell 中,键入
help
以获取可以从客户端执行的命令列表,如下所示:[zkshell: 0] help ZooKeeper -server host:port cmd args 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 delquota [-n|-b] path get [-s] [-w] path getAcl [-s] path getAllChildrenNumber path getEphemerals path history listquota path ls [-s] [-w] [-R] path ls2 path [watch] 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] rmr path set [-s] [-v version] path data setAcl [-s] [-v version] [-R] path acl setquota -n|-b val path stat [-w] path sync path
-
创建一个节点zk_test
create /zk_test zkdata
-
查看节点
ls / #显示结果如下[zk_test, zookeeper]
-
拿到刚才关联的数据
get /zk_test #显示结果zkdata
-
修改数据
set /zk_test hello
2.ZooKeeper(分布式应用程序的分布式协调服务,来自官网介绍)概述
-
Zookeeper含义
ZooKeeper 是分布式应用程序的分布式开源协调服务。它公开了一组简单的原语,分布式应用程序可以基于这些原语来实现更高级别的同步、配置维护以及组和命名服务。它被设计为易于编程,并使用以熟悉的文件系统目录树结构为样式的数据模型。它在 Java 中运行,并且具有 Java 和 C 的绑定。众所周知,协调服务很难做好。它们特别容易出现诸如竞争条件和死锁之类的错误。ZooKeeper 背后的动机是减轻分布式应用程序从头开始实现协调服务的责任。
-
设计目标
**ZooKeeper 被复制。**就像它协调的分布式进程一样,ZooKeeper 本身旨在通过一组称为集合的主机进行复制。
组成 ZooKeeper 服务的服务器必须相互了解。它们维护内存中的状态图像,以及持久存储中的事务日志和快照。只要大多数服务器(服务器节点超过半数以上)可用,ZooKeeper 服务就可用。
客户端连接到单个 ZooKeeper 服务器。客户端维护一个 TCP 连接,通过它发送请求、获取响应、获取监视事件和发送心跳。如果与服务器的 TCP 连接中断,客户端将连接到不同的服务器。
-
数据模型和分层命名空间
ZooKeeper 提供的命名空间很像标准文件系统的命名空间。名称是由斜杠 (/) 分隔的一系列路径元素。ZooKeeper 命名空间中的每个节点都由路径标识。
-
ZooKeeper节点
ZooKeeper 树中(通过上图中可以看出)的每个节点都称为znode。Znodes 维护一个 stat 结构,其中包括数据更改、ACL更改的版本号。stat 结构也有时间戳。版本号与时间戳一起允许 ZooKeeper 验证缓存并协调更新。每次 znode 的数据更改时,版本号都会增加。例如,每当客户端检索数据时,它也会收到数据的版本。并且当客户端执行更新或删除时,它必须提供它正在更改的 znode 数据的版本。如果它提供的版本与数据的实际版本不匹配,则更新将失败。
1.持久节点(PERSISENT)
定义:一旦创建,除非主动调用删除操作,否则一直存储在ZooKeeper上;
2.临时节点(EPHEMERAL)
定义:只要创建 znode 的会话处于活动状态,这些 znode 就存在。当会话结束时,znode 被删除。
创建临时节点:
create -e /testE test
这里可以再启动一个客户端来观察节点的变化,关闭创建临时节点的客户端,执行以下命令
ls /
可以看到之前创建的 /testE 节点已经被移除
注意:临时 znode 不允许有子节点。可以使用getEphemerals命令检索会话的临时列表。
3.顺序节点(SEQUENTIAL)(唯一命名)
create -s /que create -s /que create -s /que ls / 结果如下:[que0000000000, que0000000001, que0000000002, zookeeper]
4.TTL 节点(在 3.6.0 中添加)
创建 PERSISTENT 或 PERSISTENT_SEQUENTIAL znode 时,您可以选择为 znode 设置以毫秒为单位的 TTL。如果在 TTL 内没有修改 znode 并且没有子节点,它将成为服务器在未来某个时间点删除的候选节点。
5.节点的访问控制(ACL)
存储在命名空间中每个 znode 的数据是原子读写的。读取获取与 znode 关联的所有数据字节,写入替换所有数据。每个节点都有一个访问控制列表 (ACL),它限制了谁可以做什么。
ZooKeeper 使用 ACL 来控制对其 znode(ZooKeeper 数据树的数据节点)的访问。ACL 实现与 UNIX 文件访问权限非常相似:它使用权限位来允许/禁止针对节点的各种操作以及这些位适用的范围。与标准 UNIX 权限不同,ZooKeeper 节点不受用户(文件所有者)、组和世界(其他)三个标准范围的限制。ZooKeeper 没有 znode 所有者的概念。相反,ACL 指定了与这些 id 相关联的 id 和权限集。
ZooKeeper 支持以下权限:
- CREATE:您可以创建一个子节点
- 阅读:您可以从节点获取数据并列出其子节点。
- WRITE:您可以为节点设置数据
- DELETE : 可以删除子节点
- ADMIN:您可以设置权限
在CREATE和DELETE权限已被打破了出来写的更细粒度的访问控制权限。对于案件CREATE和DELETE有以下几方面:
您希望 A 能够在 ZooKeeper 节点上执行设置,但不能创建或删除子节点。
CREATE without DELETE:客户端通过在父目录中创建 ZooKeeper 节点来创建请求。您希望所有客户端都可以添加,但只有请求处理器可以删除。(这有点像文件的 APPEND 权限。)
此外,由于 ZooKeeper 没有文件所有者的概念,因此存在ADMIN权限。在某种意义上,ADMIN权限将实体指定为所有者。ZooKeeper 不支持 LOOKUP 权限(对目录执行权限位以允许您 LOOKUP,即使您无法列出目录)。每个人都隐含地拥有 LOOKUP 权限。这允许您统计一个节点,但仅此而已。(问题是,如果你想在一个不存在的节点上调用 zoo_exists() ,没有权限检查。)
ADMIN权限在 ACL 方面也有特殊作用:为了检索 znode 用户的 ACL,必须具有READ或ADMIN权限,但没有ADMIN权限,摘要哈希值将被屏蔽。
内置 ACL 方案
ZooKeeper 具有以下内置方案:
- world有一个 id,任何人,代表任何人。
- auth是一种特殊方案,它忽略任何提供的表达式,而是使用当前用户、凭据和方案。在保留 ACL 时,ZooKeeper 服务器将忽略提供的任何表达式(无论是用户喜欢 SASL 身份验证还是user:password喜欢 DIGEST 身份验证)。但是,表达式仍必须在 ACL 中提供,因为 ACL 必须与格式scheme:expression:perms匹配。提供此方案是为了方便,因为它是用户创建 znode 并将对该 znode 的访问权限仅限于该用户的常见用例。如果没有经过身份验证的用户,则使用 auth 方案设置 ACL 将失败。
- 摘要使用用户名:密码字符串生成 MD5 哈希,然后将其用作 ACL ID 身份。身份验证是通过以明文形式发送用户名:密码来完成的。在 ACL 中使用时,表达式将是username:base64编码的SHA1密码摘要。
- ip使用客户端主机 IP 作为 ACL ID 身份。的ACL表达的形式的地址/位,其中最显著位的地址是针对最显著匹配位的客户端主机的IP。
- x509使用客户端 X500 Principal 作为 ACL ID 身份。ACL 表达式是客户端的准确 X500 主体名称。使用安全端口时,客户端会自动进行身份验证并设置其 x509 方案的身份验证信息。
6.节点相关操作:
create : 在树中的某个位置创建一个节点 delete : 删除一个节点 get data : 从节点读取数据 set data :将数据写入节点 get children : 检索节点的子节点列表 sync : 等待数据被传播 ......
-
Zookeeper(Watch)监听机制
定义:客户端可以在 znode 上设置监听器。对该 znode 的更改会触发监视,然后清除监视。当监听被触发时,ZooKeeper 会向客户端发送通知。
工作原理:Zookeeper的Watcher机制主要包括客户端线程、服务端WatcherManager、Zookeeper服务器三部分,客户端在向Zookeeper服务器注册的同时,会将Watcher对象存储在客户端的WatcherManager当中,当Zookeeper服务器触发Watcher事件后,会向客户端发送通知(WatchedEvent),客户端线程从WatcherManager中取出对应的Watcher对象来执行回调逻辑。
监听的3个关键点:
-
一次性触发
当数据发生变化时,会向客户端发送一个监听 事件。例如,如果客户端执行 getData("/znode1", true) 并且稍后更改或删除了 /znode1 的数据,则客户端将获得 /znode1 的监视事件。如果 /znode1 再次更改,则不会发送监视事件,除非客户端进行了另一次读取以设置新监视。
-
发送到客户端
这意味着事件正在到达客户端的途中,但在更改操作的成功返回码到达发起更改的客户端之前可能无法到达客户端。监听异步发送给观察者。ZooKeeper 提供了排序保证:客户端永远不会看到它设置了监视的更改,直到它第一次看到监视事件。网络延迟或其他因素可能会导致不同的客户端在不同时间查看更新并返回代码。关键是不同客户端看到的一切都会有一个一致的顺序。
-
设置监听数据
这是指节点可以改变的不同方式。将 ZooKeeper 视为维护两个监听列表会有所帮助:数据监听和子监听。getData() 和 exists() 设置数据监听。getChildren() 设置子监听。或者,考虑根据返回的数据类型设置监听可能会有所帮助。getData() 和 exists() 返回有关节点数据的信息,而 getChildren() 返回子节点列表。因此, setData() 将触发正在设置的 znode 的数据监听(假设设置成功)。成功的 create() 将触发正在创建的 znode 的数据观察和父 znode 的子观察。成功的 delete() 将同时触发数据观察和子观察(因为不能再有子节点)被删除的 znode 以及父 znode 的子观察。
持久监听
**3.6.0 中的新功能:**现在在上述标准监听上有一个变体,您可以设置一个在触发时不会被移除的监听。此外,这些监视会触发事件类型NodeCreated、NodeDeleted和*NodeDataChanged ,*并且可以选择递归地针对所有从监视注册的 znode 开始的 znode。请注意,NodeChildrenChanged事件不会为持久递归观察触发,因为它是多余的。
使用addWatch()方法设置持久监听。触发语义和保证(一次性触发除外)与标准监听相同。关于事件的唯一例外是递归持久观察者永远不会触发子更改事件,因为它们是多余的。使用具有观察者类型*WatcherType.Any 的**removeWatches()*移除持久观察。
-
-
Zookeeper统计结构
czxid 导致创建此 znode 的更改的 zxid。 mzxid 最后修改此 znode 的更改的 zxid。 pzxid 最后修改此 znode 的子节点的更改的 zxid。 ctime 从创建这个 znode 的纪元开始的时间(以毫秒为单位)。 mtime 上次修改此 znode 时从纪元开始的时间(以毫秒为单位)。 version 该 znode 的数据更改次数。 cversion 此 znode 的子节点的更改次数。 aversion 此 znode 的 ACL 的更改次数。 ephemeralOwner 如果 znode 是临时节点,则此 znode 的所有者的会话 ID。如果它不是临时节点,它将为零。 dataLength 此 znode 的数据字段的长度。 numChildren 此 znode 的子节点数。 `` version 该 znode 的数据更改次数。 cversion 此 znode 的子节点的更改次数。 aversion 此 znode 的 ACL 的更改次数。 ephemeralOwner 如果 znode 是临时节点,则此 znode 的所有者的会话 ID。如果它不是临时节点,它将为零。 dataLength 此 znode 的数据字段的长度。 numChildren 此 znode 的子节点数。