目录
部分图片来自百战尚学堂
1、概念
ZooKeeper是一个开放源代码的分布式协调服务。ZooKeeper的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。
说明:
Zookeeper顾名思义就是动物园管理员。 因为Hadoop生态各个项目都是动物得图标。 所以很符合管理员得形象。
2、什么是Zookeeper
Zookeeper是文件系统+监听机制。
3、如何下载
点击下面的链接,进入apache官网即可下载zookeeper的tar包
4、部署运行
4.1、解压文件
通过第三步的链接下载好zookeeper的tar包后,通过将zookeeper的tar包拉入虚拟机中
通过tar -zxvf 包名 -C zookeeper 将文件夹取名为zookeeper安装到当前目录中
4.2、修改配置文件
zookeeper在conf目录中提供了一个参考的配置类名为zoo_sample.cfg,但是zookeeper加载的配置类名为zoo.cfg,所以我们可以创建一个副本或者直接将zoo_sanple.cfg改名为zoo.cfg
mv zoo_sample.cfg zoo.cfg
然后我们需要修改一下zoo.cfg目录
在目录中添加这两段代码,这两段代码的意思就是配置zookeeper运行过后产生的文件存放到dataDir指定的路径中,产生的日志存放到dataLogDir指定的路径中
dataDir=/usr/local/zookeeper/apache-zookeeper-3.8.1-bin/zkdata
dataLogDir=/usr/local/zookeeper/apache-zookeeper-3.8.1-bin/zklogs
4.3、创建持久化目录
通过以下命令创建目录
mkdir zkdata
mkdir zklogs
4.4、配置jdk
因为zookeeper是通过java编写的,所以zookeeper在运行的时候是需要jdk的环境变量的,通过以下命令配置jdk环境变量,既然配置了jdk的环境变量那么顺便把zookeeper的环境变量一起配置了吧(我的linux系统中jdk已经下好了,如果大家还没有下载jdk的可以前往oracle官网下载)
1、编辑配置类
vim /etc/profile
2、在配置类中添加以下语句
大家根据自己的文件名修改配置,JAVA_HOME对应的就是jdk的文件名,ZOOKEEPER_HOME对应的即使zookeeper的文件名
export JAVA_HOME=/usr/local/jdk/jdk-11.0.17
export ZOOKEEPER_HOME=/usr/local/zookeeper/apache-zookeeper-3.8.1-bin
export PATH=$PATH:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin
3、生成环境变量
source /etc/profile
4.5、启动zookeeper服务
因为我们已经配置好了zookeeper的环境变量此时我们就可以不需要进入bin目录才能使用zookeeper。
通过以下命令启动zookeeper服务
zkServer.sh start
4.6、查看zookeeper运行状态
启动好zookeeper之后是这样的
此时我们可以通过以下代码查看zookeeper的运行状态
zkServer.sh status
5、系统模型
5.1、数据模型(文件系统)
在Zookeeper中,可以说 Zookeeper中的所有存储的数据是由znode组成的,节点也称为 znode,并以 key/value 形式存储数据。
树
介绍:
整体结构类似于 linux 文件系统的模式以树形结构存储。其中根路径以 / 开头。
保存数据
注意:
以 key/value 形式存储数据。key就是znode的节点路径,比如 /java , /server。
5.2、znode节点类型
ZooKeeper 节点是有生命周期的,这取决于节点的类型。节点类型可以分为持久节点、临时节点,以及时序节点,具体在节点创建过程中,一般是组合使用,可以生成以下 4 种节点类型。
持久节点
持久节点是zookeeper中最常见的一种节点类型。所谓持久节点,是指改数据节点被创建后,就会一直存在与zookeeper服务器上,直到有删除操作来主动清除这个节点。
持久顺序节点
这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。
示例:
/java00000000000001 spring
/baizhan00000000000001 itbaizhan
临时节点
- 从名称上可以看出该节点的一个最重要的特性就是临时性。
- 所谓临时性是指,如果将节点创建为临时节点,那么该节点数据不会一直存储在 ZooKeeper 服务器上。
区别:
和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。
临时顺序节点
临时顺序节点的基本特性和临时节点是一致的,同样是在临时节点的基础上,添加了顺序的特性。
示例:
/baizhan0000000000000001 itbaizhan
/baizhan0000000000000002 itbaizhan
/baizhan0000000000000003 itbaizhan
5.3、客户端操作命令
首先运行一下代码进入zookeeper客户端
zkCli.sh
进入客户端之后是这样的
1、查看节点
通过ls /查看根路径下有哪些文件
2、新增节点
通过create /文件名 文件值创建节点
3、获取节点数据
通过get /文件名获取文件中的数据
4、设置节点数据
通过set /文件名 文件值设置节点数据
5、删除节点(无子节点)
通过delete /文件名 删除节点(如果该节点下面有子节点那么需要先删除子节点再删除父节点)
5.4、监听机制
监听节点的变化
ls -w path
通过该命令监听节点的变化,不是值的变化。
示例:
此时如果我们删除该节点即会提示
监听节点的值的变化
get -w path
watch监听机制只能够使用一次,如果下次想要使用,必须重新监听,就比如ls path watch命令,只能监听节点路径的改变一次,如果还想监听,那么需要再执行一次ls path watch命令。
示例:
此时如果我们修改节点里面的值即会提示
6、apache的curator操作zookeeper
Curator是 Netflix公司开源的一套ZooKeeper客户端框架。和ZkClient一样,Curator解决了很多ZooKeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和 NodeExistsException异常等,目前已经成为了Apache的顶级项目,是全世界范围内使用最广泛的ZooKeeper客户端之一。
Curator包
- curator-framework:对zookeeper的底层api的一些封装。
- curator-client:提供一些客户端的操作,例如重试策略等。
- curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等。
6.1、添加依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
6.2、创建会话并连接
//创建会话
String add = "地址:2181";//多个地址用逗号隔开
CuratorFramework cur = CuratorFrameworkFactory
.builder()
.connectionTimeoutMs(1000)//连接超时时间
.connectString(add)//连接地址
.retryPolicy(new ExponentialBackoffRetry(1000, 3))//连接超时重试
.build();
//连接
cur.start();
6.3、操作命令
创建节点
//创建节点
//withMode()设置节点类型
//forPath()设置节点key和value
cur.create().withMode(CreateMode.PERSISTENT).forPath("/node2","node2".getBytes());
获取节点的值
//获取节点数据
byte[] bytes = cur.getData().forPath("/node2");
System.out.println(new String(bytes));
获取节点的所有子节点
1、获取节点的子节点
//getChildren()获取所有子节点
//forPath()获取谁的子节点
List<String> child = cur.getChildren().forPath("/node2");
for(Stringc:child){
System.out.println(c);
}
修改节点
1、设置节点数据
//setData()根据key设置value
//forPath()提供key和value
cur.setData().forPath("/node2","helloworld!".getBytes());
删除节点(无子节点)
1、删除节点
//delete()根据key删除节点
//forPath()提供key
cur.delete().forPath("/node2");
递归删除节点(有子节点)
1、删除节点时,该节点有子节点,此时需要递归删除
//delete()删除节点
//deletingChildrenIfNeeded()递归删除节点
//forPath()提供删除节点的key
cur.delete().deletingChildrenIfNeeded().forPath("/node2");
监听机制
1、监听机制(可以监听无数次)
//NodeCache监听对象
//getListenable().addListener()添加监听机制,并设置如何监听
//start()开启监听
NodeCache cache=new NodeCache(cur,"/node2");
cache.getListenable().addListener(()->{
System.out.println("被修改了...");
});
cache.start();
Thread.sleep(Long.MAX_VALUE);