🎄ZooKeeper 主要应用功能
🎯分布式配置管理:ZooKeeper可以用来进行分布式系统的配置管理
,例如可以将一些全局参数存储在ZooKeeper中
,并且可以动态地更新这些配置。**【举例说明】**一个分布式系统需要连接到数据库,在连接信息发生变化时,可以将新的数据库连接信息存储在ZooKeeper中,并通知所有相关的节点更新配置
。
🎯服务注册和发现:ZooKeeper可以作为命名服务
来提供统一的命名空间,并帮助分布式系统实现服务注册发现
的功能。**【举例说明】**在一个集群环境中,各个节点可以通过ZooKeeper来注册自己提供的服务
,并获取其他节点提供的服务地址,从而实现服务发现。
🎯分布式锁:ZooKeeper提供了分布式锁的实现,可以帮助分布式系统协调各个节点的并发访问控制。**【举例说明】**在分布式环境中,多个节点可能需要同时访问共享资源,利用ZooKeeper的分布式锁可以确保只有一个节点能够访问共享资源,从而避免竞争条件。
🎯集群管理:ZooKeeper自身就是一个集群系统,可以用来管理整个集群
的状态信息。他是一个分布式的、开源的分布式应用程序的协调服务
-> 实际上干活的还是各个结点 ZooKeeper只进行协调管理
🎄ZooKeeper的安装和配置
可见 :ZooKeeper的安装和配置
🎄ZooKeeper的命令
🍭ZooKeeper数据模型
(1)ZooKeeper是一个树形目录服务,其数据模型和UNIX的文件系统目录很相似,拥有一个层次化的结构
(2)这里面的每一个节点都被称为ZNode,每一个节点上都会保存自己的数据和结点信息
(3)结点可以拥有子节点,同时也允许存储少量的(1MB)数据存储在该节点下
(4)结点可以分为四大类:
- PERSTSTENT 持久化结点
- EPHEMERAL 临时结点 -e
- PERSTSTENT_SEQUENTIAL 持久化顺序结点 -s
- EPHEMERAL_SEQUENTIAL 临时顺序结点 -es
🍭ZooKeeper的命令操作
ZooKeeper的命令操作包括服务端、客户端方面
🌴服务端的操作
服务端的操作非常简单
(1)启动ZooKeeper服务:./bin/zkServer.sh start
(2)查看ZooKeeper服务:./bin/zkServer.sh status
(3)停止ZooKeeper服务:./bin/zkServer.sh stop
(4)重启ZooKeeper服务:./bin/zkServer.sh restart
🌴客户端的操作
(1)ZooKeeper客户端连接服务端(指定IP + 端口) `./zkCli.sh -server localhost:2181`
(2)查看根目录下的列表:`ls /`
(3)创建节点:`create /目录结构 指定要存的数据`
(4)获取节点下存储的数据:`get /目录结构`
(5)为节点设置存储的数据:`set /目录结构 指定要存的数据`
(6)删除结点:`delete /指定目录结构`
(7)联级删除:`deleteall`
(8)临时结点`只在当前的会话有效 ` `create -e /目录结构`
(9)顺序结点的创建 `create -s /目录结构`
(10)临时顺序结点的创建 `create -es /目录结构`
🔮持久化结点的相关操作
(1)ZooKeeper客户端连接服务端(指定IP + 端口) ./zkCli.sh -server localhost:2181
(2)查看根目录下的列表:ls /
(3)创建节点:create /目录结构 指定要存的数据
(4)获取节点下存储的数据:get /目录结构
(5)为节点设置存储的数据:set /目录结构 指定要存的数据
(6)删除结点:delete /指定目录结构
(7)联级删除:deleteall
(8)注意:不可级联创建结点
🔮临时
结点的创建
临时结点
只在当前的会话有效
create -e /目录结构
🔮顺序
结点的创建
命名默认是顺序的
create -s /目录结构
**🔮临时顺序
结点的创建 ** create -es /目录结构
🎄ZooKeeper的JavaAPI
操作
对应下图的
ZooKeeper Java API
🍭Curator介绍
Curator是Apache ZooKeeper的Java客户端库 演变过程:
原生JavaAPI -> ZkClient -> Curator
🍭Curator API常用操作
🌱前置Maven配置
<!-- 使用Curator操作ZooKeeper -->
<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>
<!--junit4-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
⚡创建zkApiTest
类进行测试
连接客户端 ->
client
变量接收客户端连接对象❗注意:代码中的🎯
.namespace("bbm")
绑定名称空间 可以简化操作,也就是说 之后的所有操作都是在远程ZooKeeper的/bbm
目录下操作
public class zkApiTest {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);
private static final String connectString = "node1:2181";
// 定义客户端连接
private static CuratorFramework client = null;
@Before
public void init() throws IOException {
// 创建一个客户端的连接
client = CuratorFrameworkFactory.builder().connectString(connectString)
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retryPolicy)
🎯.namespace("bbm") // 绑定名称空间 简化操作
.build();
client.start(); // 创建之后进行start之后才能操作远程的ZooKeeper
}
@After
public void close() {
// 释放资源
if(client != null) client.close();
}
}
⚡连接客户端的两种方式
/**
* Curator建立连接 第一种方式 CuratorFrameworkFactory.newClient(..)
*/
@Test
public void setUpConnection() {
/**
* @Param connectString – list of servers to connect to 连接字符串 地址和端口("192.168.12.3:2181, 192.168.12.4"2181")
* @Param sessionTimeoutMs – session timeout 会话超时时间
* @Param connectionTimeoutMs – connection timeout 连接超时时间
* @Param retryPolicy – retry policy to use 重试策略
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);
CuratorFramework client = CuratorFrameworkFactory.newClient("node1:2181", 60 * 1000, 15 * 1000, retryPolicy);
client.start(); // 测试客户端是否能正常连接和运行
}
/**
* Curator建立连接 第2种方式 使用建造者模式进行创建
*/
@Test
public void setUpConnection2() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);
CuratorFramework client = CuratorFrameworkFactory.builder().connectString("node1:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retryPolicy)
.namespace("bbm") // 绑定名称空间 简化操作
.build();
client.start();
}
⚡创建节点
(创建多种节点)
创建节点 -> 持久、临时、顺序、数据(和shell操作是对应的)
(1)基本创建 (2)创建带有数据的结点 (3)设置结点的类型 (4)创建多级结点/app1/p1
(1)基本创建 -> 默认创建的是持久化的结点
@Test
public void createNode() throws Exception {
// (1) 基本创建
String str = client.create().forPath("/app1_202311301614");
System.out.println("str = " + str);
}
查看创建后的结果:
如果创建节点的时候没有指定存储的数据
则默认存储客户端的IP地址: