ZooKeeper
zookeeper是一个经典的分布式数据一致性解决方案,致力于分布式应用提供一个高性能,高可用,而且具有严格顺序访问控制能力的分布式协调储存服务。
zookeeper 应用场景
-
维护配置信息
-
分布式锁服务
-
集群管理
-
生成分布式唯一id
属性说明
-
cZxid 数据节点创建时的事物ID
-
ctime 数据节点创建时的时间
-
mZxid 数据节点最后一次更新时的事物id
-
mtime 数据节点最后一次更新时的时间
-
cversion 子节点的更改次数
-
dataVersion 节点数据的更改次数
-
aclVersion 节点ACL的更改次数
-
ephemeralOwner 如果节点是临时节点,则表示创建该节点会话的SessionID,如果该节点是持久节点,则该属性为0
-
dataLength 数据内容的长度
-
numChildren 数据节点当前的子节点个数
zookeeper安装和配置
- 下载 官方下载地址
- 移动zookeeper至Linux服务器上,并解压
tar -zxvf ****.tar.gz
- 进入conf 目录
cp zoo_sample.cfg zoo.cfg
- zookeeper根目录下创建data目录,并修改zoo.cfg配置
mkdir data
cd conf
vim zoo.cfg
修改dataDir 为 刚才所创建的data目录位置
- zookeeper基本命令
#进入zk的bin目录
./zkServer.sh start
#关闭zk
#./zkServer.sh stop
./zkServer.sh status
#以下内容为zookeeper状态
#==============================
#ZooKeeper JMX enabled by default
#Using config: /opt/zookeeper-3.6.2/bin/../conf/zoo.cfg
#Client port found: 2181. Client address: localhost. Client SSL: false.
#Mode: standalone
#==================================
#登录zk
./zkCli.sh
zookeeper 常用shell命令
- 新增节点
create [-s] [-e] path data # -s 是有序节点,-e 临时节点
- 获取节点数据
get path # 返回属性,数据
stat path # 只返回属性,没有数据
- 更新节点
set path newValue
set path newValue [version] #当你输入的版本与当前版本号不同时,修改失败
- 删除节点
delete path [version]
# 如果被删除节点含有子节点时
rmr path # 递归删除
- 查看某节点的子节点
ls path # 仅输出子节点
ls2 path # 输出子节点,和当前节点属性
监听器
get path watch # 获取当前节点属性,并且之后当前节点发生改变后,向当前客户端告知该节点发生变化
ls path watch # 监听子节点
zookeeper 的 acl 权限控制
权限模式
方案 | 描述 |
---|---|
world | 只有一个用户:anyone,代表登录zk的所有人(默认) |
ip | 对客户端使用的ip地址认证 |
auth | 使用以添加认证的用户认证 |
digest | 使用 用户名 密码 方式认证 |
授予的权限
相关命令
setAcl path world:anyone:<acl> # 设置权限
getAcl path # 获取对应节点的权限属性
addauth digest <user>:<password> # 添加认证用户
setAcl <path> auth:<user>:<acl>
超级管理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ixpF6evw-1620963436816)(http://img.zzzyuan.cn/image-20210329082927491.png)]
Curator
Curator框架提供了一套高级的API, 简化了ZooKeeper的操作
- 解决session会话超时重连
- watcher 反复注册
- 简化了api
- 遵循fluent风格的api
- 提供了分布式锁服务,共享计算器,缓存机制等
引入jar包
<dependencies>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.6.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.6.0</version>
</dependency>
</dependencies>
基本API
基本创建连接
//创建连接对象
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("127.0.0.1:2181,127.0.0.1:2182")
.sessionTimeoutMs(5000) // 超时时间
.retryPolicy(new ExponentialBackoffRetry(1000, 3)) // 超时重连策略
.namespace("create") // 命名空间
.build();
// 启动
client.start();
// 关闭
client.close();
创建节点
client.create()
.withMode(CreateMode.EPHEMERAL)
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
.forPath("/path","data".getBytes());
//异步创建
client.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.EPHEMERAL)
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
.inBackground(new BackgroundCallback() {
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("异步创建回调函数");
}
})
.forPath("/path","data".getBytes())
自定义授权模式
List<ACL> list = new ArrayList<ACL>();
list.add(new ACL(ZooDefs.Perms.ALL,new Id("ip","127.0.0.1")));
client .create()
.withMode(CreateMode.EPHEMERAL)
.withACL(list)
.forPath("/path","data".getBytes());
创建多个节点
// 递归创建节点树
client.create()
.withMode(CreateMode.EPHEMERAL)
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
.forPath("/path/node/node2","data".getBytes());
更新节点
client.setData()
.forPath("/path","new Data".getBytes());
//带上版本号
client.setData()
.withVersion(0)
.forPath("/path","new Data".getBytes());
//异步修改
client.setData()
.inBackground(new BackgroundCallback() {
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("异步修改回调函数");
}
})
.forPath("/path","new Data".getBytes());
删除
client.delete()
.forPath("path");
//删除其子节点
client.delete()
.deletingChildrenIfNeeded()
.forPath("/path");
client.delete()
.inBackground(new BackgroundCallback() {
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("异步删除回调函数");
}
})
.forPath("/path");
获取值
//获取值
client.getData()
.forPath("/path");
//异步获取值
client.getData()
.inBackground(new BackgroundCallback() {
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("异步GET回调函数");
}
})
.forPath("/path");
//获取其属性和值
Stat stat = new Stat();
client.getData()
.storingStatIn(stat)
.forPath("path");
//获取子节点
client.getChildren()
.forPath("/path");
检查节点是否存在
client.checkExists().forPath("/path");
监听机制
监听当前节点
NodeCache nodeCache = new NodeCache(client, "/path");
nodeCache.start();
nodeCache.getListenable().addListener(new NodeCacheListener() {
public void nodeChanged() throws Exception {
System.out.println("节点变化时调用");
// 获取当前节点数据
nodeCache.getCurrentData().getData();
nodeCache.getCurrentData().getPath();
}
});
nodeCache.close();
监听子节点
final PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/path", true);
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
System.out.println("子节点变化时调用");
// 获取当前节点数据
pathChildrenCacheEvent.getData().getPath();
}
});
事务
client.inTransaction()
.create().forPath("/path","data".getBytes())
.and()
.setData().forPath("/path","newData".getBytes())
.and()
.commit();
分布式锁
排他锁
//排他锁
InterProcessLock interProcessLock = new InterProcessMutex(client, "/lock");
//获取锁
interProcessLock.acquire();
//释放锁
interProcessLock.release();
读写锁
//读写锁
InterProcessReadWriteLock interProcessReadWriteLock = new InterProcessReadWriteLock(client, "/path");
//拿锁
InterProcessLock writeLock = interProcessReadWriteLock.writeLock();
InterProcessLock readLock = interProcessReadWriteLock.readLock();
writeLock.acquire();
readLock.acquire();
//释放锁
writeLock.release();
readLock.release();
相关命令
监控
- 用户在客户端使用 telnet 或 nc 向zookeeper提交相关命令
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ndWFrdUV-1620963436818)(http://img.zzzyuan.cn/image-20210331125914488.png)]