ZooKeeper 入门

ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 Hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

认识 Apache ZooKeeper

文件系统

ZooKeeper 提供了一个多层级的节点命名空间。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。ZooKeeper 为了保证高吞吐和低延迟,在内存中维护了一个树状的目录结构,使得 ZooKeeper 不能用于存放大量的数据,每个节点的存放数据上限为 1M。

四种类型的节点

  1. PERSISTENT – 持久化目录节点
  2. PERSISTENT_SEQUENTIAL – 持久化顺序编号目录节点
  3. EPHEMERAL – 临时目录节点
  4. EPHEMERAL_SEQUENTIAL – 临时顺序编号目录节点

Watcher 机制

针对每个节点的操作,都会有一个监督者 watcher,当监控的某个对象(znode)发生了变化,则触发 watcher 事件。ZooKeeper 的 watcher 是一次性的,触发后立即销毁。

父节点、子节点增删改都能够触发其 watcher。

对于不同类型的操作,触发 watcher 事件也不同:

  1. (子)节点创建事件
  2. (子)节点删除事件
  3. (子)节点数据变化事件

设置 watcher

get path [watch]

watcher 事件类型:

  • NodeCreated:创建父节点触发
  • NodeDataChanged:修改父节点数据触发
  • NodeDeleted:删除父节点触发
  • NodeChildrenChanged:创建、删除子节点触发

ACL(Access Control Lists) 权限控制

针对节点 key 设置相关读写等权限,保障数据安全性。权限 permissions 可以指定不同的权限范围以及角色。

getAcl:获取某个节点的 ACL 权限信息
setAcl:设置某个节点的 ACL 权限信息
addauth:输入认证授权信息

ACL 构成
[schema:id:permissions]

  • schema:代表采用的某种权限机制
  • id:代表允许访问的用户
  • permissions:权限组合字符串

schema
world:world 下只有一个 id,即只有一个用户,也就是 anyone
world:anyont:[permissions]

auth:代表认证登录,需要注册用户有权限,明文
auth:password:[permissions]

digest:需要对密码加密才能访问,密文
digest:username:BASE64(SHA1(password)):[permissions]

ip:限制 ip 进行访问
ip:192.168.1.101:[permissions]

super:超级管理员,拥有所有权限

permissions
权限字符串缩写 crdwa

  • CREATE:创建子节点
  • READ:获取节点/子节点
  • DELETE:删除子节点
  • WRITE:设置节点数据
  • ADMIN:设置权限

ZooKeeper 用途

命名服务

通过指定的名字来获取资源或者服务地址,利用 ZooKeeper 创建一个全局路径,这个路径可以作为一个名字,提供服务地址,或者一个远程对象。

配置管理

将程序的配置信息存放在 ZooKeeper 的节点下,当有配置发生改变时,即节点发生变化,通过 watch 机制通知对应客户端更改配置。

分布式锁

保持独占:将 ZooKeeper 的一个节点看作一把锁,通过创建节点 /distribute_lock 的方式实现加锁,由最终成功创建节点的客户端拥有锁,使用后删除节点便可释放锁。
控制时序:当锁节点 /distribute_lock 已经存在时,所有客户端在它下面创建临时顺序目录子节点,由编号最小的获得锁,用完删除节点便可释放锁。

ZooKeeper 注意事项

客户端的读请求可以被集群中的任意一台机器处理;写请求会发送给所有机器并达成一致后,才会返回成功。因此,随着 ZooKeeper 的集群机器增多,读请求的吞吐量会提高但是请求的吞吐会下降。

ZooKeeper 具有有序性,更新都是全局有序的,每个更新都有一个唯一的时间戳 zxid(ZooKeeper Transaction Id)。

ZooKeeper 四字命令

stat:查看 ZooKeeper 的状态信息,以及是否 mode
ruok:查看当前 ZooKeeper 是否启动,返回 imok
dump:列出未经处理的会话和临时节点
conf:查看服务器配置
cons:展示连接到服务器的客户端信息
envi:环境变量
mntr:监控 Zookeeper 的健康信息
wchs: 展示 watch 信息
wchc、wchp:session 与 watch 及 path 与 watch 信息

ZooKeeper 的 原生 API 调用

ZooKeeper API 的核心部分是 org.apache.zookeeper.ZooKeeper 类。它提供了在其构造函数中连接 ZooKeeper 集合的选项,并具有以下方法:

  • connect - 连接到ZooKeeper集合
  • create- 创建znode
  • exists- 检查znode是否存在及其信息
  • getData - 从特定的znode获取数据
  • setData - 在特定的znode中设置数据
  • getChildren - 获取特定znode中的所有子节点
  • delete - 删除特定的znode及其所有子项
  • close - 关闭连接

连接 ZooKeeper

注意
本地 Java 程序连接虚拟机 Linux 的 ZooKeeper 时,需把虚拟机的 IP 配置在本地 C:\Windows\System32\drivers\etc\hosts 中,否则,会导致连接超时。

引入 ZooKeeper 依赖

    <dependencies>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
        </dependency>
    </dependencies>

使用构造方法连接

    ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)

参数:

  • connectString:连接服务器的 ip 字符串,比如"192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181",可以是一个 ip,也可以是多个 ip,一个 ip 代表单机,多个 ip 代表集群
  • sessionTimeout:超时时间
  • watcher:通知事件,如果有对应的事件触发,则会收到一个通知
  • canBeReadOnly:可读,当这个物理机节点断开后,还是可以读到数据的,只是不能写,此时数据被读取到的可能是旧数据,不推荐使用

操作 ZooKeeper

  1. 创建 Znode
// 同步创建
String create(final String path, byte data[], List<ACL> acl, CreateMode createMode)
// 异步创建
void create(final String path, byte data[], List<ACL> acl, CreateMode createMode,  StringCallback cb, Object ctx)

参数:

  • path:Znode 路径
  • data:要存储在指定 Znode 路径中的数据
  • acl:要创建的节点的访问控制列表
  • createMode:节点的类型
  • cb:回调
  1. 修改 Znode 数据
// 同步修改
Stat setData(final String path, byte data[], int version)
// 异步修改
void setData(final String path, byte data[], int version, StatCallback cb, Object ctx)

参数:

  • version:Znode 的当前版本。每当数据更改时,ZooKeeper 会更新 Znode 的版本号
  1. 删除 Znode
// 同步删除
void delete(final String path, int version)
// 异步删除
void delete(final String path, int version, VoidCallback cb, Object ctx)
  1. 查看 Znode
// 同步查看
byte[] getData(String path, Watcher watcher, Stat stat)
// 异步查看
void getData(final String path, Watcher watcher, DataCallback cb, Object ctx)

参数:

  • watcher:监视器类型的回调函数。当指定 Znode 的数据改变时,ZooKeeper 集合将通过监视器回调进行通知。这是一次性通知。
  • stat:返回 Znode 的元数据。
  1. 检查 Znode 是否存在
// 同步检查
Stat exists(final String path, Watcher watcher)
// 异步检查
void exists(final String path, Watcher watcher, StatCallback cb, Object ctx)
  1. 获取 Znode 的子节点
// 同步获取子节点
List<String> getChildren(final String path, Watcher watcher)
// 异步获取子节点
void getChildren(final String path, Watcher watcher, ChildrenCallback cb, Object ctx)
void getChildren(final String path, Watcher watcher, Children2Callback cb, Object ctx)

参数:
ChildrenCallback:获取子节点的回调
Children2Callback:获取子节点及其 stat 的回调

不足之处

  1. 不支持自动超时重连,需要手动操作
  2. Watch 注册一次后会失效
  3. 不支持递归创建节点

参考

  1. GitHub 代码
  2. ZooKeeper 分布式专题与 Dubbo 微服务入门
  3. ZooKeeper 的 W3C 教程
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐