1、持久化节点
2、临时节点
3、顺序节点
4、ttl和容器节点
5、临时节点不能存在子节点
6、同一级节点不能存在相同的名称
1.Client 初始化连接,状态转为 CONNECTING(①)
2.Client 与 Server 成功建立连接,状态转为 CONNECTED(②)
3.Client 丢失了与 Server 的连接或者没有接受到 Server 的响 应,状态转为 CONNECTING(③)
4.Client 连上另外的 Server 或连接上了之前的 Server,状态 转为 CONNECTED(②)
5.若会话过期(是 Server 负责声明会话过期,而不是 Client ), 状态转为 CLOSED(⑤),状态转为 CLOSED
6.Client 也可以主动关闭会话(④),状态转为 CLOSED
zookeeper 为数据节点引入了版本的概念,每个数据节点都有三 类版本信息,对数据节点任何更新操作都会引起版本号的变化
版本有点和我们经常使用的乐观锁类似。这里有两个概念说 一下,一个是乐观锁,一个是悲观锁
悲观锁:是数据库中一种非常典型且非常严格的并发控制策 略。假如一个事务 A 正在对数据进行处理,那么在整个处理 过程中,都会将数据处于锁定状态,在这期间其他事务无法 对数据进行更新操作。
乐观锁:乐观锁和悲观锁正好想法,它假定多个事务在处理 过程中不会彼此影响,因此在事务处理过程中不需要进行加 锁处理,如果多个事务对同一数据做更改,那么在更新请求 提交之前,每个事务都会首先检查当前事务读取数据后,是 否有其他事务对数据进行了修改。如果有修改,则回滚事务 再回到 zookeeper,version 属性就是用来实现乐观锁机制的 “写入校验”
zookeeper 提供了分布式数据的发布/订阅功能,zookeeper 允许客户端向服务端注册一个 watcher 监听,当服务端的一 些指定事件触发了 watcher,那么服务端就会向客户端发送一个事件通知。
值得注意的是,Watcher 通知是一次性的,即一旦触发一次 通知后,该 Watcher 就失效了,因此客户端需要反复注册 Watcher,即程序中在 process 里面又注册了 Watcher,否则, 将无法获取 c3 节点的创建而导致子节点变化的事件。
Ip 通 过 ip 地 址 粒 度 来 进 行 权 限 控 制 , 例 如 配 置 [ip:192.168.0.1], 或者按照网段 ip:192.168.0.1/24 ;
Digest:最常用的控制模式,类似于 username:password ; 设 置 的 时 候 需 要 DigestAuthenticationProvider.generateDigest() SHA- 加 密 和 base64 编码
World: 最开放的控制模式,这种权限控制几乎没有任何作 用,数据的访问权限对所有用户开放。 world:anyone
Super: 超级用户,可以对节点做任何操作
指权限赋予的用户或一个指定的实体,不同的权限模式下,授权对象 不同
指通过权限检查后可以被允许的操作,create /delete /read/write/admin
Create 允许对子节点 Create 操作
Read 允许对本节点 GetChildren 和 GetData 操作
Write 允许对本节点 SetData 操作
Delete 允许对子节点 Delete 操作 Admin 允许对本节点 setAcl 操作
权 限 模 式 : Schema 和 授 权 对 象 : 比 如 ip 地 址 、 username:passwrod 用来确定权限验证过程中使用的验证策略。
IP: 通过 ip 地址来做权限控制,比如 ip:192.168.1.1 表示权 限控制都是针对这个 ip 地 址 的 。 也 可 以 针 对 网 段 ip:192.168.1.1/24
Digest : 最 常 用 的 权 限 控 制 模 式 , 类 似 于 username:password 形式来进行权限控制;
World: 开放的权限控制模式,数据节点的访问权限对所有 用 户 开 放 , 也 可 以 看 作 是 一 种 特 殊 的 Digest 模 式 world:anyone
super: 表示超级用户,可以对任意 zookeeper 上的数据节 点进行操作
public class CuratorDemo {
private static final String CONNECTION_STR="localhost:2181";
//PathChildCache --针对于子节点的创建、删除和更新 触发事件
//NodeCache 针对当前节点的变化触发事件
//TreeCache 综合事件
public static void main(String[] args) throws Exception {
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
.connectString(CONNECTION_STR).sessionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
curatorFramework.start();
/**
* 重试策略:Curator 内部实现的几种重试策略:
* • ExponentialBackoffRetry:重试指定的次数, 且每一次重试之
* 间停顿的时间逐渐增加.
* • RetryNTimes:指定最大重试次数的重试策略
* • RetryOneTime:仅重试一次
* • RetryUntilElapsed:一直重试直到达到规定的时间
*/
// CRUD
//curatorFramework.create(); // create
//curatorFramework.setACL(); // 修改
//curatorFramework.delete(); // 删除
//curatorFramework.getData(); // 获取
createData(curatorFramework);
}
private static void createData(CuratorFramework curatorFramework) throws Exception {
curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT)
.forPath("/data/program","test".getBytes());
}
private static void updateData(CuratorFramework curatorFramework) throws Exception {
curatorFramework.setData().forPath("/data/program", "up".getBytes());
}
private static void deleteData(CuratorFramework curatorFramework) throws Exception {
Stat stat = new Stat();
String value = new String(curatorFramework.getData().storingStatIn(stat).forPath("/data/program"));
curatorFramework.delete().withVersion(stat.getVersion()).forPath("/data/program");
}
public void acl() throws Exception {
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
.connectString(CONNECTION_STR).sessionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
curatorFramework.start();
List<ACL> list = new ArrayList<>();
ACL acl = new ACL(ZooDefs.Perms.READ, new Id("digest", DigestAuthenticationProvider.generateDigest("admin:admin")));
list.add(acl);
curatorFramework.create().withMode(CreateMode.PERSISTENT).withACL(list).forPath("/auth");
}
}
Watcher 监听机制是 Zookeeper 中非常重要的特性,我们基 于 zookeeper 上创建的节点,可以对这些节点绑定监听事件,比如可以监听节点数据变更、节点删除、子节点状态变更等 事件,通过这个事件机制,可以基于 zookeeper 实现分布式 锁、集群管理等功能
watcher 机制有一个特性:当数据发生改变的时候,那么 zookeeper 会产生一个 watch 事件并发送到客户端,但是客 户端只会收到一次这样的通知,如果以后这个数据再发生变 化,那么之前设置 watch 的客户端不会再次收到消息。因为 他是一次性的;如果要实现永久监听,可以通过循环注册来实现。
Curator 提供了三种 Watcher 来监听节点的变化
-
PathChildCache:监视一个路径下孩子结点的创建、删 除、更新。
-
NodeCache:监视当前结点的创建、更新、删除,并将 结点的数据缓存在本地。
-
TreeCache:PathChildCache 和 NodeCache 的“合体”, 监视路径下的创建、更新、删除事件,并缓存路径下所 有孩子结点的数据。
public class WatcherDemo {
private static final String CONNECTION_STR="localhost:2181";
public static void main(String[] args) throws Exception {
//PathChildCache --针对于子节点的创建、删除和更新 触发事件
//NodeCache 针对当前节点的变化触发事件
//TreeCache 综合事件
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().
connectString(CONNECTION_STR).sessionTimeoutMs(5000).
retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
curatorFramework.start();
addListenerWithNode(curatorFramework);
System.in.read();
}
//配置中心
//创建、修改、删除
private static void addListenerWithNode(CuratorFramework curatorFramework) throws Exception {
NodeCache nodeCache=new NodeCache(curatorFramework,"/watch",false);
NodeCacheListener nodeCacheListener = () -> {
System.out.println("receive Node Changed");
System.out.println(nodeCache.getCurrentData().getPath()+"---"+new String(nodeCache.getCurrentData().getData()));
};
nodeCache.getListenable().addListener(nodeCacheListener);
nodeCache.start();
}
//实现服务注册中心的时候,可以针对服务做动态感知
private static void addListenerWithChild(CuratorFramework curatorFramework) throws Exception {
PathChildrenCache nodeCache = new PathChildrenCache(curatorFramework,"/watch",true);
PathChildrenCacheListener nodeCacheListener = (curatorFramework1, pathChildrenCacheEvent) -> {
System.out.println(pathChildrenCacheEvent.getType()+"->"+new String(pathChildrenCacheEvent.getData().getData()));
};
nodeCache.getListenable().addListener(nodeCacheListener);
nodeCache.start(PathChildrenCache.StartMode.NORMAL);
}
}