Zookeeper使用手册
ZooKeeper是什么?
ZooKeeper是一个开源的分布式协调服务,它为我们提供了高可用、高性能、稳定的分布式数据一致性解决方案,通常被用于实现订阅/发布、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。
ZooKeeper的特点
- 顺序一致性:所有提交到ZooKeeper服务的请求,都会严格按照顺序执行。
- 原子性:所有事务请求的处理结果在集群内所有机器上的应用情况是一致的。
- 单一系统映像:无论客户端连接到集群内的哪一台机器,所查看到的数据模型都是一致的。
- 可靠性:一旦一次请求被应用,更改的结果将会被持久化,直到下一次更改覆盖。
ZooKeeper数据模型
ZooKeeper的多叉树形结构
ZooKeeper数据模型采用的是层次化的多叉树形结构,每个节点都可以存储数据,可以存储数字、字符串、二进制序列,每个节点存储数据最大为1M。每个节点都有一个唯一路径,根节点路径用"/"来标识,每个节点都被称为znode,是最小的数据单元。
树节点znode
树节点类型
树节点类型分为4类:
- 持久(PERSISTENT)节点:一旦创建就一直存在于ZooKeeper集群的节点,即使是宕机恢复依然存在,直到制动删除节点。
- 临时(EPHEMERAL)节点:临时节点的生命周期与客户端会话绑定,会话消失则节点消失。临时节点只能是叶子节点,不能是子节点。
- 持久顺序(PERSISTENT_SEQUENTIAL)节点:除了拥有持久节点的特性,子节点的名称还具有顺序性。
- 临时顺序(EPHEMERAL_SEQUENTIAL)节点:除了拥有临时节点的特性,节点的名称还具有顺序性。
znode的数据类型
znode节点包含两部分数据:
- stat:状态信息。Stat 类中包含了一个数据节点的所有状态信息的字段,包括节点版本version、事务 ID-cZxid、节点创建时间-ctime 和子节点个数-numChildren 等等。
- data:节点存放数据的具体内容
ACL权限控制
节点操作权限
对于znode的操作权限,ZooKeeper提供了以下5种:
- CREATE:能创建子节点
- DELETE:能删除子节点
- WRITE:能设置/更新节点数据
- READ:能获取节点数据和列出子节点
- ADMIN:能设置节点的acl权限。
身份认证提供的方式
- world : 默认方式,所有用户都可无条件访问。
- auth :不使用任何 id,代表任何已认证的用户。
- digest :用户名:密码认证方式: username:password 。
- ip : 对指定 ip 进行限制。
ZooKeeper的Watcher(事件监听机制)
ZooKeeper 允许用户在指定节点上注册一些 Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是 ZooKeeper 实现分布式协调服务的重要特性。
会话(Session)
Session 可以看作是 ZooKeeper 服务器与客户端的之间的一个 TCP 长连接,通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向 ZooKeeper 服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的 Watcher 事件通知。
ZooKeeper集群
为了保证高可用,推荐以集群形态部署ZooKeeper,集群通常部署单数数量的ZooKeeper服务。ZooKeeper集群采用ZAB协议,保持数据一致性。 
集群角色
| 角色 | 说明 |
|---|---|
| Leader | 为客户端提供读和写的服务,负责投票的发起和决议,更新系统状态。 |
| Follower | 为客户端提供读服务,如果是写服务则转发给 Leader。参与选举过程中的投票。 |
| Observer | 为客户端提供读服务,如果是写服务则转发给 Leader。不参与选举过程中的投票,也不参与“过半写成功”策略。在不影响写性能的情况下提升集群的读性能。此角色于 ZooKeeper3.3 系列新增的角色。 |
zookeeper实战
zkCli
zkCli是zookeeper官方提供的用于连接zookeeper服务的命令行工具。使用如下命令连接zookeeper服务:
shell
sh zkCli.sh -server 127.0.0.1:2181zookeeper常用命令
help:通过help命令查看常用指令介绍ls path:ls+节点路径命令显示指定节点的所有子节点。-s表示显示节点状态,-R表示递归显示节点下所有孙子节点。stat path:stat+节点路径命令显示节点状态create path [data]:命令在指定路径下创建一个节点,同时设置节点数据delete path:命令删除指定路径的节点,节点需要为叶子节点deleteall path:命令删除指定路径下的节点及其孙子节点。set path data:设置节点数据get path data:获取节点数据
zookeeper java客户端Curator的简单使用
- 引如Curator的相关依赖
xml
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.3.0</version>
</dependency>- 使用curator-framework生成zookeeper客户端,连接zookeeper并操作。
java
public class MyZookeeperStudyApplication {
public static void main(String[] args) throws Exception {
//重试策略
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
CuratorFramework zkClient = CuratorFrameworkFactory.builder().connectString("43.136.117.138:2181").retryPolicy(retryPolicy).build();
//连接zookeeper
zkClient.start();
//判断节点是否存在
if (zkClient.checkExists().forPath("/a") == null) {
//在指定路径下创建一个持久节点
zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/a");
}
//设置指定路径节点的数据
zkClient.setData().forPath("/a", "abc".getBytes());
//读取指定路径节点的数据
System.out.println(new String(zkClient.getData().forPath("/a")));
//删除指定路径的节点
zkClient.delete().deletingChildrenIfNeeded().forPath("/a");
if (zkClient.checkExists().forPath("/temp") == null) {
//在指定路径下创建一个临时节点
zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/temp");
}
zkClient.setData().forPath("/temp", "temp".getBytes());
System.out.println(new String(zkClient.getData().forPath("/temp")));
//获取指定路径的子节点
List<String> list = zkClient.getChildren().forPath("/zookeeper");
for (String str : list
) {
System.out.println(str);
}
}
}