Zookeeper概念
Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务。
Zookeeper 翻译过来就是动物园管理员,他是用来管Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)的管理员。简称zk
Zookeeper 是一个分布式的、开源的分布式应用程序的协调服务。
Zookeeper提供的主要功能包括
配置管理
分布式锁
集群管理
Zookeeper数据模型
ZooKeeper是一个树形目录服务,其数据模型和Unix的文件系统目录树很类似,拥有一个层次化结构。
这里面的每一个节点都被称为: ZNode,每个节点上都会保存自己的数据和节点信息。
节点可以拥有子节点,同时也允许少量(1MB)数据存储在该节点之下。
节点可以分为四大类:
PERSISTENT持久化节点
EPHEMERAL 临时节点: -e
PERSISTENT SEQUENTIAL 持久化顺序节点:-s
EPHEMERAL SFOUENTIAL临时顺序节点: -es
Zookeeper服务端常用命令
启动ZooKeeper服务: ./zkServer.sh start
查看 ZooKeeper服务状态: ./zkServer.sh status
停止 ZooKeeper服务: /zkServer.sh stop
重启 ZooKeeper服务: ./zkServer.sh restart
Zookeeper客户端常用命令
本机启动./zkCli.sh -server localhost:2181
create /app1 shun
get /app1
delete /app1
set /app1 shun2
ls /
创建子节点
create /app1/p1
create /app1/p2
deleteall /app1 删除全部节点包括子节点
help帮助
Corator介绍
Curator Apache ZooKeeper 的Java客户端库。
常见的ZooKeeper Java API :
原生Java API
ZkClient
Curator
Curator 项目的目标是简化 ZooKeeper客户端的使用。
Curator最初是 Netfix 研发的,后来捐献了Apache基金会,目前是Apache的顶级项目。
官网: http://curator.apache.org/
Curator API常用操作
建立连接
添加节点
删除节点
修改节点
查询节点
Watch事件
监听
分布式锁实现
建立连接
pom文件
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!--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>
<!--日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
test测试目录下创建连接
package com.itheima.curator;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Test;
public class CuratorTest {
@Test
public void testConnect(){
/**
*@param connectString – 连接字符串 zk server 地址和端口"192.168.157.9:2181,192.168.157.10:2181"
*@param sessionTimeoutMs – 会话超时时间 单位ms
*@param connectionTimeoutMs – 连接超时时间 单位ms
*@param retryPolicy – 重试策略
* Params:
* retryCount – the number of times retried so far (0 the first time)
* elapsedTimeMs – the elapsed time in ms since the operation was attempted
* sleeper – use this to sleep - DO NOT call Thread.sleep
*/
//重试策略
RetryPolicy retry = new ExponentialBackoffRetry(3000,10);
// //1、第一种方式
// CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.157.9:2181",
// 60 * 1000, 15 * 1000, retry);
//2、第二种方式
// CuratorFrameworkFactory.Builder
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("192.168.157.9:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retry).namespace("itheima").build();
//你做的所有操作都认为itheima是zoorkeeper的跟目录
//开启连接
client.start();
}
}
添加节点
package com.itheima.curator;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class CuratorTest {
CuratorFramework client;
/**
* 创建连接
*/
@Before
public void testConnect(){
/**
*@param connectString – 连接字符串 zk server 地址和端口"192.168.157.9:2181,192.168.157.10:2181"
*@param sessionTimeoutMs – 会话超时时间 单位ms
*@param connectionTimeoutMs – 连接超时时间 单位ms
*@param retryPolicy – 重试策略
* Params:
* retryCount – the number of times retried so far (0 the first time)
* elapsedTimeMs – the elapsed time in ms since the operation was attempted
* sleeper – use this to sleep - DO NOT call Thread.sleep
*/
//重试策略
RetryPolicy retry = new ExponentialBackoffRetry(3000,10);
// //1、第一种方式
// CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.157.9:2181",
// 60 * 1000, 15 * 1000, retry);
//2、第二种方式
// CuratorFrameworkFactory.Builder
client = CuratorFrameworkFactory.builder()
.connectString("192.168.157.9:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retry).namespace("itheima").build();
//你做的所有操作都认为itheima是zoorkeeper的跟目录
//开启连接
client.start();
}
/**
* 创建节点 create 持久 临时 顺序 数据
* 1、基本创建 create().forPath("");
* 2、创建节点、带有数据 create().forPath("",data);
* 3、设置节点的类型 create().withMode(CreateMode(枚举)).forPath("");
* 4、创建多级节点 create().creatingParentsIfNeeded().forPath("/app4/p1");
*
*
*/
@Test
public void testCreate() throws Exception {
//1、基本创建
//如果创建节点,没有指点数据 则默认指定当前客户端的IP作为数据
String path = client.create().forPath("/app1");
System.out.println(path);
}
@Test
public void testCreate2() throws Exception {
//2、基本创建 带有数据的
String path = client.create().forPath("/app2","hehe".getBytes());
System.out.println(path);
}
@Test
public void testCreate3() throws Exception {
//3、设置节点的类型
//默认类型:持久化
String path = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3");
System.out.println(path);
}
@Test
public void testCreate4() throws Exception {
//4、创建多级节点 /app1/p1
//creatingParentsIfNeeded 如果父节点不存在 则构建父节点
String path = client.create().creatingParentsIfNeeded().forPath("/app4/p1");
System.out.println(path);
}
@After
public void close(){
if (client!=null){
client.close();
}
}
}
查询节点
/**
* 查询节点
* 1、查询数据:get: getData().forPath("")
* 2、查询子节点: ls getChildren().forPath("")
* 3、查询节点状态选项 ls -s getData().storingStatIn(状态对象).getPath("")
*
*/
@Test
public void testGet1() throws Exception {
//1、查询数据:get
byte[] path = client.getData().forPath("/app2");
System.out.println(path);
}
@Test
public void testGet2() throws Exception {
//2、查询子节点: ls
List<String> path = client.getChildren().forPath("/");
System.out.println(path);
}
@Test
public void testGet3() throws Exception {
Stat status = new Stat();
//2、查询节点的状态信息 ls -s
client.getData().storingStatIn(status).forPath("/app1");
System.out.println(status);
}
修改数据
/**
* 修改数据
* 1、基本修改数据 setData().forPath()
* 2、根据版本修改 setData().withVersion().forPath()
* version 是通过查询出来的 目的就是为了让其他客户不会干扰我 保证原子性
*/
@Test
public void testSet() throws Exception {
client.setData().forPath("/app1","itcast".getBytes());
}
@Test
public void testSetForVersion() throws Exception {
Stat status = new Stat();
//2、查询节点的状态信息 ls -s
client.getData().storingStatIn(status).forPath("/app1");
int version = status.getVersion(); //查询出来的
System.out.println(version);
client.setData().withVersion(version).forPath("/app1","haha".getBytes());
}
删除节点
/**
* 删除节点 delete deleteall
* 1、删除单个节点 delete().forPath("")
* 2、删除带有子节点的节点 delete().deletingChildrenIfNeeded().forPath("")
* 3、必须成功的删除为了防止网络抖动 本质是重试 delete().guaranteed().forPath("");
* 4、回调 delete().guaranteed().inBackground(方法).forPath("");
* @throws Exception
*/
@Test
public void testDelete1() throws Exception {
//1、删除单个节点
client.delete().forPath("/app1");
}
@Test
public void testDelete2() throws Exception {
//2、删除带有子节点的节点
client.delete().deletingChildrenIfNeeded().forPath("/app4");
}
@Test
public void testDelete3() throws Exception {
//3、必须成功的删除
client.delete().guaranteed().forPath("/app2");
}
@Test
public void testDelete4() throws Exception {
//4、回调
client.delete().guaranteed().inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("我被删除了");
System.out.println(client);
System.out.println(event);
}
}).forPath("/app1");
}
Curator API 常用操作 - Watch事件监听
ZooKeeper 允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候, ZooKeeper服务端会将事件通知到感兴趣的客户端上去,该机制是ZooKeeper实现分布式协调服务的重要特性。
ZooKeeper中引入了Watcher机制来实现了发布/订阅功能能,能够让多个订阅者同时监听某一个对象,当一个对象自身状态变化时,会通知所有订阅者。
ZooKeeper 原生支持通过注册Watcher来进行事件监听,但是其使用并不是特别方便·需要开发人员自己反复注册Watcher,比较繁琐。
Curator引入了Cache来实现对ZooKeeper服务端事件的监听。
ZooKeeper提供了三种Watcher:
NodeCache:只是监听某一个特定的节点
PathChildrenCache:监控一个ZNode的子节点.
TreeCache:可以监控整个树上的所有节点,类似于PathChildrenCache和NodeCache的组合
package com.itheima.curator;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
public class CuratorWatcherTest {
CuratorFramework client;
/**
* 创建连接
*/
@Before
public void testConnect(){
/**
*@param connectString – 连接字符串 zk server 地址和端口"192.168.157.9:2181,192.168.157.10:2181"
*@param sessionTimeoutMs – 会话超时时间 单位ms
*@param connectionTimeoutMs – 连接超时时间 单位ms
*@param retryPolicy – 重试策略
* Params:
* retryCount – the number of times retried so far (0 the first time)
* elapsedTimeMs – the elapsed time in ms since the operation was attempted
* sleeper – use this to sleep - DO NOT call Thread.sleep
*/
//重试策略
RetryPolicy retry = new ExponentialBackoffRetry(3000,10);
// //1、第一种方式
// CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.157.9:2181",
// 60 * 1000, 15 * 1000, retry);
//2、第二种方式
// CuratorFrameworkFactory.Builder
client = CuratorFrameworkFactory.builder()
.connectString("192.168.157.9:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retry).namespace("itheima").build();
//你做的所有操作都认为itheima是zoorkeeper的跟目录
//开启连接
client.start();
}
@After
public void close(){
if (client!=null){
client.close();
}
}
/**
* 演示 NodeCache: 给指定一个节点注册监听器
*/
@Test
public void TestNodeCache() throws Exception {
//1、创建NodeCache对象
final NodeCache nodeCache = new NodeCache(client,"/app1");
//2、注册监听
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("节点变化~");
//获取修改节点后的数据
byte[] data = nodeCache.getCurrentData().getData();
System.out.println(data.toString());
}
});
//3、开启监听 如果设置为true 则开启监听是,加载缓存数据
nodeCache.start(true);
while (true){
}
}
/**
* 演示 PathChildrenCache: 监听某个节点的所有子节点们
*/
@Test
public void testPathChildrenCache() throws Exception {
//1、创建PathChildrenCache对象
PathChildrenCache pc = new PathChildrenCache(client,"/app2",true);
//2、绑定监听器
pc.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event) throws Exception {
System.out.println("子节点变化了~");
System.out.println(event);
//监听子节点的数据变更,并且拿到变更后的数据
//1、获取类型
PathChildrenCacheEvent.Type type = event.getType();
//2、判断类型是否是update
if (type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
System.out.println("数据变了~");
byte[] data = event.getData().getData();
System.out.println(data.toString());
}
}
});
//3、开启
pc.start();
while (true){
}
}
/**
* 演示 TreeCache: 监听某个节点自己和所有子节点们
*/
@Test
public void treeTreeCache() throws Exception {
//1、创建监听器
TreeCache treeCache = new TreeCache(client, "/app2");
//2、注册监听
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
System.out.println("节点变化了~");
System.out.println(event);
}
});
//3、开启
treeCache.start();
while (true){
}
}
}