Zookeeper
学习目标
-
定义:是一个分布式的、开源的协调服务(中间件)
-
作用:
- 配置管理
- 用来管理服务的信息(ip、端口、服务提供功能接口),例如连接数据库的配置信息。
- 分布式锁
- 用户控制服务的资源,锁住之后,只能有一个服务科操作,其它服务等待
- 集群管理
- 用于管理服务的节点(每个节点提供的服务相同,则组成一个集群),组成(高可用)
- 配置管理
-
场景:
-
原理/架构:
- 架构
-
Znode是根节点衍生出的
- 持久化
-
临时节点 客户断开之后,则节点自动删除
- 持久化顺序节点,子节点会按照数字自增的方式创建
- 临时顺序节点
-
使用:
-
命令行(liunx)
- 登录 zhCli.-service ip:端口(2181)
- 查看节点有哪些子节点: ls /节点名
- 查看节点详细信息:ls -s /节点
- 创建节点 :create /目录 节点名 数据 (create /app1 itheima)
- 获取数据 : get /节点名
- 设置数据: set /节点名数据
- 删除节点: delete /节点名
- 删除节点包含子节点: deleteall /节点名
-
临时节点
- create -e ,临时节点
-
顺序节点
- create -s /顺序节点
-
临时顺序节点
- create -es /临时顺序节点
-
API方式
-
连接客户端
-
连接客户端
- 方式1
步骤1.导入坐标
<!--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>
步骤2.获得链接对象
// 1.使用CuratorFrameworkFactory对象获取链接对象 //重试策略 3000 代表3秒尝试重试一次,一共重试10次 RetryPolicy rp = new ExponentialBackoffRetry(3000,10); //2.获取链接 CuratorFramework client = CuratorFrameworkFactory.newClient("1270.0.1:2181", 3000, 3000, rp);
-
开启链接
client.start();
- 方式2 参数同上
//client.start(); build = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181").connectionTimeoutMs(15 * 1000).sessionTimeoutMs(60 * 1000).retryPolicy(rp).namespace("WSL").build(); //开启链接 build.start();
API创建节点
- 创建持久化节点 语法:连接对象.create().forPath("/节点名");
build.create().forPath("/test");
- 创建临时节点: 连接对象.create().withMode(“创建类型”).forPath("/节点名")
build.create().withMode(CreateMode.EPHEMERAL).forPath("/节点名字")
- 创建持久化顺序节点: 连接对象.create().withMode(“创建类型”).forPath("/节点名")
build.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/节点名")
- 创建临时节点:连接对象.create().withMode(“创建类型”).forPath("/节点名")
build.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/节点名")
查询节点信息
- 查询数据 get : 连接对象.getData().forPath()
//先创建一个持久性节点,并设置值
build.create().forPath("/test","hhh".getBytes());
//从节点中获取值的格式是:连接对象.getData().forPath("/节点路径")
byte[] bytes = build.getData().forPath("/test");
String s = new String(bytes);
System.out.println(s);
- 查询某个节点下所有的子节点:ls :getChildren().forPath("/路径")
List<String> strings = build.getChildren().forPath("/");
System.out.println(strings);//执行结果[test2, test]
- 查询节点的完整状态信息:getData.storingStatIn(Stat对象).forPath("/查询节点路径")
//保存查询节点状态信息
Stat stat = new Stat();
byte[] bytes = build.getData().storingStatIn(stat).forPath("/test2");
System.out.println(stat);//查询的结果内容110,110,1595861595448,1595861595448,0,0,0,0,0,0,10
修改节点
- 普通修改 连接对象.setData().forPath("/节点路径",“修改的内容”.getBytes());
//修改节点信息
build.setData().forPath("/test","itheima".getBytes());
//从新查询修改的信息
byte[] bytes = build.getData().forPath("/test");
System.out.println(new String(bytes));
2. 执行版本进行修改
Stat stat = new Stat();
build.getData().storingStatIn(stat).forPath("/test");
//修改只想版本对应的内容
build.setData().withVersion(stat.getVersion()).forPath("/test","修改数据".getBytes());
//取出修改后的内容
byte[] bytes = build.getData().forPath("/test");
System.out.println(new String(bytes));//输出结果:修改数据
删除节点
-
删除单个节点
build.delete().forPath("/test2");
//先查询有WSL节点下有哪些子节点 List<String> strings = build.getChildren().forPath("/"); System.out.println("删除前子节点"+strings); //删除test2的节点 build.delete().forPath("/test2"); //再次查询 List<String> strings1 = build.getChildren().forPath("/"); System.out.println("删除后的子节点"+strings1); /* 删除前子节点[test2, test] 删除后的子节点[test] */
-
删除带有子节点的节点
//删除这个test和app1 build.delete().deletingChildrenIfNeeded().forPath("/test");
-
必须成功的删除(在网络有波动的情况下,一次删除可以能不成功,需要尝试几次)
//使用必须删除成功的方法,在网络有波动的情况下, 可以会删除失败,使用这个方法的本质就是重试几次 build.delete().guaranteed().forPath("/test");
4. 回调 (不仅仅只有删除才有,增、改、查,都有)
```java
//先创建一个持久性的节点
build.create().inBackground(new BackgroundCallback() {
/**
*
* @param curatorFramework 这是链接对象
* @param curatorEvent 封装了节点的状态详细信息
* @throws Exception
*/
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
System.out.println("创建了");
System.out.println(curatorEvent);
}
}).forPath("/test");
执行后的结果
ZK监听机制
-
统一步骤
-
创建监听对象
NodeCache node=new NodeCache(连接对象,"/被监听的节点路径");
-
注册监听
node.getListenable.addListener(new NodeCacheListener(){ @Override public void nodeChanged() throws Exception { //这就是监听后需要处理的流程 } })
-
开启监听
node.start();
-
-
NodeCache:只监听特定子节点的删、该、创建事件
//1.创建监听 NodeCache nodeCache = new NodeCache(build, "/test"); //2.注册监听器 getListenable->获取监听器,addListener添加监听,添加监听对象,用于监听 nodeCache.getListenable().addListener(new NodeCacheListener() { @Override public void nodeChanged() throws Exception { System.out.println("test节点发生了改变"); } }); //3.开启监听 nodeCache.start();
-
PathChildrenCache:监听一个节点的子节点
//创建PathChildrenCache对象 构造方法中的true表示的是开启子节点的缓存数据,可以拿到子节点内容 PathChildrenCache pathChildrenCache = new PathChildrenCache(build, "/",true); //注册监听 pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() { /** * * @param curatorFramework 这是连接对象 * @param pathChildrenCacheEvent 缓冲区里面的内容 * @throws Exception */ @Override public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception { System.out.println("子节点发生了变化"); System.out.println(pathChildrenCacheEvent); //可以判断是增删改的那种事件 PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType(); //如果是更改操作就提示更新 if(type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){ System.out.println("内容被更新了"); byte[] data = pathChildrenCacheEvent.getData().getData(); System.out.println("更新后的内容:"+new String(data)); } //监听了添加事件 else if(type.equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){ System.out.println("添加了节点"); ChildData data = pathChildrenCacheEvent.getData(); System.out.println("节点路径:"+data.getPath()); } //监听删除事件 else if(type.equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){ System.out.println("子节点删除"); ChildData data = pathChildrenCacheEvent.getData(); System.out.println("被删除的节点路径:"+data.getPath()); } } }); //开启监听 pathChildrenCache.start();
-
ThreeCache:监听一个节点并包含所有的子节点和
//创建监听对象 TreeCache treeCache = new TreeCache(build, "/"); //注册监听对象 treeCache.getListenable().addListener(new TreeCacheListener() { @Override public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception { System.out.println("节点变化了"); System.out.println(treeCacheEvent); } }); //3.开启节点监听 treeCache.start();
分布式锁[了解]
-
定义:协调跨机器的进程之间的数据同步问题
原理
集群角色和职责
k, TreeCacheEvent treeCacheEvent) throws Exception {
System.out.println(“节点变化了”);
System.out.println(treeCacheEvent);
}
});
//3.开启节点监听
treeCache.start();
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200810182620413.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dzbF9Dbg==,size_16,color_FFFFFF,t_70)
## 分布式锁[了解]
- 定义:协调跨机器的进程之间的数据同步问题
原理
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200810182437873.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dzbF9Dbg==,size_16,color_FFFFFF,t_70)
### 集群角色和职责
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200810182604180.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dzbF9Dbg==,size_16,color_FFFFFF,t_70)