文章目录
- 1. zookeeper
- 2. zookeeper安装
- 3. zookeeper运行
- 4. zookeeper操作
- (1) 服务端常用命令操作
- (2) 客户端常用命令
- (3) javaAPI操作
- Curator
- Curator基本操作
- 节点操作
- watch事件监听
- 分布式锁
- 5. zookeeper集群
- (1) 集群搭建
- (2) 集群启动
- 6. 图形化页面工具ZooInspector
1. zookeeper
1. zookeeper是Apache hadoop 项目下的一个子项目,是一个树形目录服务
2. zookeeper翻译过来就是动物园管理员,用来管理Hadoop(大象),hive(蜜蜂),pig(小猪)的管理员
3. zookeeper是一个分布式的,开源的分布式引用程序的协调服务
功能包括:
1. 配置管理
2. 分布式锁
3. 集群管理
2. zookeeper安装
前提: 安装jdk
- 下载zookeeper
- 上传到linux解压
- 配置zoo.cfg,安装目录下的conf目录中
cp zoo_sample.cfg zoo.cfg
# 数据目录设置
dataDir=/path/to/zookeeper_data
# 客户端连接端口
clientPort=2181
3. zookeeper运行
服务端启动:
# 使用zkServer start启动
zkServer start
# 查看服务节点状态
zkServer.sh status
# 停止节点
zkServer.sh stop
standalone为单节点模式(孤独的):
4. zookeeper操作
数据模型: zookeeper是一个树形目录服务,其数据模型和Unix的文件系统很类似,拥有一个层次化结构。每一个节点都被称为ZNode,每个节点上都会保存自己的数据和节点信息。节点可以拥有子节点,同时也允许少量(1MB)数据存储在该节点之下。
节点分为四大类:
PERSISTENT 持久化节点
EPHEMERAL 临时节点 -e
PERSISTENT_SEQUENTIAL 持久化顺序节点 -s
EPHEMERAL_SEQUENTIAL 临时顺序节点 -es
(1) 服务端常用命令操作
zkServer.sh start # 开启服务
zkServer.sh stop # 停止服务
zkServer.sh status # 查看状态
zkServer.sh restart # 重启
(2) 客户端常用命令
zkCli.sh -server localhost:2181 # 连接服务端(默认连接本地2181)
quit # 退出
ls [-s -w -R] path #查看目录文件
create [-e -s -es] path # 创建节点默认持久化,支持子节点,,如: /a1/b1
get path # 获取节点数据
set path 内容 # 给节点设置内容
delete path # 删除节点
deleteall path # 删除所有节点,包括子节点
ls2 path # 节点详细信息: ls -s (效果相同)
help # 查看帮助文档
(3) javaAPI操作
Curator
Curator是APache Zookeeper的java客户端
常见的zookeeper javaAPI:
原生java API
ZkClient
Curator
Curator项目的目标是简化zookeeper客户端的使用
Curator官网: https://curator.apache.org/
Curator基本操作
maven坐标:
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>4.1.0</version></dependency>
建立连接:
// 方式一CuratorFramework clent = CuratorFrameworkFactory.newClient("192.168.72.88:2181", // 连接地址,集群使用,隔开5000, // 会话超时时间3000, // 连接超时时间new ExponentialBackoffRetry(3000, 10) // 重试策略);client.start(); //开启连接
// 方式二: 如果指定了命名空间,就会以指定的目录为根目录,可以做到隔离和简化效果CuratorFramework build = CuratorFrameworkFactory.builder().connectString("192.168.72.88:2181").sessionTimeoutMs(5000).connectionTimeoutMs(3000).namespace("test") // 命名空间.retryPolicy(new ExponentialBackoffRetry(3000, 10)).build();build.start();
节点操作
创建节点:
// 基本创建, 在根目录下创建xjy节点,数据为hello("可选,默认当前客户端的ip")client.create().forPath("/xjy", "hello" .getBytes());
// 创建指定模式的节点
client.create().withMode(CreateMode.CONTAINER).forPath("/xjy2");
// 创建多级节点
client.create().creatingParentsIfNeeded().forPath("/xjy2/aa");
查询节点:
// 查询节点数据
byte[] bytes = client.getData().forPath("/xjy");
String s = new String(bytes);
System.out.println(s);
// 查询子节点
List<String> list = client.getChildren().forPath("/");for (String s : list) {System.out.println(s);
}
// 查询节点状态信息
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("xjy");
System.out.println(stat);
删除数据:
修改数据:
client.setData().forPath("xjy","hello".getBytes());// 根据版本修改数据
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("xjy");
int version = stat.getVersion();
client.setData().withVersion(version).forPath("xjy","haha".getBytes());
删除数据:
// 删除单个节点
client.delete().forPath("xjy");//删除带有子节点的节点
client.delete().deletingChildrenIfNeeded().forPath("xjy");// 必须删除
client.delete().guaranteed().forPath("xjy");// 回调函数
client.delete().guaranteed().inBackground((curatorFramework, curatorEvent) -> {System.out.println("删除节点: " + curatorEvent.getPath() + " 状态: " + curatorEvent.getResultCode() + " 类型: " + curatorEvent.getType());}).forPath("xjy");
watch事件监听
zookeeper允许用户在指定节点上注册一些watcher,并且在一些特定事件触发的时候,zookeeper服务端会将时间通知到感兴趣的客户端上去,该机制是zookeeper实现分布式协调服务的重要特性
zookeeper引入了watche机制来实现了发布/定略功能,能够让多个定略者,同时监听某一个对象,当一个对象自身状态变化时,会通知到定略者。
curator引入了cache来实现对zookeeper服务端事件的监听
zookeeper提供了三种watcher:
**NodeCache **: 只监听某一个特定的节点
pathChildrenCache: 监控一个ZNode的子节点
TreeCache: 监听整个数的所有节点
监听器实现:
NodeCache nodeCache = new NodeCache(client,"/xjy",false); // 是否压缩,获取数据时候需要解压缩(但是数据传输更快)nodeCache.getListenable().addListener(() -> {System.out.println("节点数据发生变化,新数据为:" + new String(nodeCache.getCurrentData().getData())); });nodeCache.start(); //开启监听
分布式锁
在进行单机应用开发的时候,涉及到并发同步的时候,我们使用synchronized或者lock的方式啦解决多线程代码同步问题,这里的多线程在同一个jvm之下,
如果是分布式集群,属于多个jvm的工作环境,跨jvm之间无法通过多线程的锁解决同步问题
跨机器之间,可以使用第三方的进行锁
zookeeper分布式锁原理:
核心思想:
- 当客户端想要获取锁,则创建节点,使用锁,则删除节点
- 客户端获取锁时,在lock节点下创建临时顺序的节点
- 然后获取lock下面的所有子节点,客户端获取到的所有子节点后,如果发现自己创建的子节点序号最小,那么就认为该客户端获取到了锁,使用完锁后,将该节点删除
- 如果发现自己创建的节点并非lock所有子节点最小的,说明没有获取锁,此时客户端需要找到比自己小的那个节点,同时对其注册事件监听器,监听删除事件
- 如果发现比自己小的那个节点被删除,则客户端的Watcher会收到通知,如果是则获取到了锁,如果不是则重复以上步骤继续获取到比自己小的一个节点并注册监听
锁实现:
InterprocessSemaphoreMutex: 分布式排它锁(非可重入锁)
InterProcessMutex: 分布式可重如排它锁
InterProcessReadWriteLock: 分布式读写锁
InterProcessMultiLock: 将多个锁作为单个实体管理的容器
InterProcessSemaphoeV2: 共享信号量
InterProcessMutex lock = new InterProcessMutex(client, "/lock");try {lock.acquire(3, TimeUnit.SECONDS); //获取锁// 业务逻辑}finally {lock.release(); // 释放锁}
5. zookeeper集群
leader选举:
Serverid: 服务id: 编号越大选择算法的权重最大
Zxid: 数据ID: 服务器中存放的最大数据Id
投票选举: 选票过半后选举成功
角色:
1. leader领导者:
1) 处理事务请求
2) 激趣内部个服务器的调度者
2. Followe 跟随者
1) 处理客户端非事务请求,转发事务请求给Leader服务器
2) 参与Leader选举投票
3. Observer观察者
1) 处理客户端非事务请求,转发事务请求给Leader服务器
(1) 集群搭建
- 准备三台zookeeper机器
- 每台机器的zookeeper安装目录下创还能**myid文件,**编写自己的服务id
- 配置zoo.cfg配置文件
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/kk/export/soft/zookeeper370/data # 数据目录
clientPort=2181
server.1=192.168.72.88:2888:3888
server.2=192.168.72.89:2888:3888
server.3=192.168.72.90:2888:3888
(2) 集群启动
# 分别在每台上启动即可
zkServer.sh start
6. 图形化页面工具ZooInspector
下载:
将安装包解压后:
运行jar包:
连接zookeeper:
页面展示: