标签:关系 miss gets 同步 自定义 分布式配置 更改 事件 writer
统一命名服务
、分布式配置管理
、分布式消息队列
、分布式锁
、分布式协调
等功能。全局数据一致
:每个 server 保存一份相同的数据副本,client 无论连 接到哪个 server,展示的数据都是一致的,这是最重要的特征;
可靠性
:如果消息被其中一台服务器接受,那么将被所有的服务器接受。
顺序性
:包括全局有序和偏序两种:全局有序是指如果在一台服务器上 消息 a 在消息 b 前发布,则在所有 Server 上消息 a 都将在消息 b 前被 发布;偏序是指如果一个消息 b 在消息 a 后被同一个发送者发布,a 必将排在 b 前面。
数据更新原子性
:一次数据更新要么成功(半数以上节点成功),要么失 败,不存在中间状态;
实时性
:Zookeeper 保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。
临时节点
:该节点的生命周期依赖于创建它们的会话。一旦会话结束,临时节点将被自动删除,当然可以也可以手动删除。临时节点不允许拥有子节点。永久节点
:该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。"%10d"
(10 位数字,没有数值的数位用 0 补充,例如“0000000001”)。PERSISTENT
:永久节点EPHEMERAL
:临时节点PERSISTENT_SEQUENTIAL
:永久节点、序列化EPHEMERAL_SEQUENTIAL
:临时节点、序列化一次性触发
:事件发生触发监听,一个 watcher event 就会被发送到设置监听的客户端,这种效果是一次性的,后续再次发生同样的事件,不会再次触发。
事件封装
:ZooKeeper 使用 WatchedEvent 对象来封装服务端事件并传递。WatchedEvent 包含了每一个事件的三个基本属性: 通知状态
(keeperState),事件类型
(EventType)和节点路径
(path)。
event 异步发送
:watcher 的通知事件从服务端发送到客户端是异步的。
先注册再触发
:Zookeeper 中的 watch 机制,必须客户端先去服务端注册监听,这样事件发送才会触发监听,通知给客户端。
create [-s] [-e] path data
-s
:表示创建有序节点-e
:表示创建临时节点create /test 1234
## 子节点
create /test/node1 node1
## 完整的节点名称是a0000000001
create /a a
Created /a0000000001
## 完整的节点名称是b0000000002
create /b b
Created /b0000000002
create -e /a a
## 完整的节点名称是a0000000001
create -e -s /a a
Created /a0000000001
set [path] [data] [version]
path
:节点路径data
:数据version
:版本号set /test aaa
## 修改子节点
set /test/node1 bbb
dataVersion
)不正确,拒绝修改set /test aaa 1
delete [path] [version]
path
:节点路径version
:版本号,版本号不正确拒绝删除delete /test
## 版本号删除
delete /test 2
rmr /test
get path
## 获取节点详情
get /node1
## 节点内容
aaa
cZxid = 0x6
ctime = Sun Apr 05 14:50:10 CST 2020
mZxid = 0x6
mtime = Sun Apr 05 14:50:10 CST 2020
pZxid = 0x7
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 1
cZxid
:数据节点创建时的事务 ID。ctime
:数据节点创建时间。mZxid
:数据节点最后一次更新时的事务 ID。mtime
:数据节点最后一次更新的时间。pZxid
:数据节点的子节点最后一次被修改时的事务 ID。cversion
:子节点的更改次数。dataVersion
:节点数据的更改次数。aclVersion
:节点 ACL 的更改次数。ephemeralOwner
:如果节点是临时节点,则表示创建该节点的会话的 SessionID。如果节点是持久化节点,值为 0。dataLength
:节点数据内容的长度。numChildren
:数据节点当前的子节点的个数。stat path
stat
命令和get
命令相似,不过这个命令不会返回节点的数据,只返回节点的状态属性。stat /node1
## 节点状态信息,没有节点数据
cZxid = 0x6
ctime = Sun Apr 05 14:50:10 CST 2020
mZxid = 0x6
mtime = Sun Apr 05 14:50:10 CST 2020
pZxid = 0x7
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 1
ls path
和ls2 path
两个命令。后者是前者的增强,不仅会返回节点列表还会返回当前节点的状态信息。ls path
:ls /
## 仅仅返回节点列表
[zookeeper, node1]
ls2 path
:ls2 /
## 返回节点列表和当前节点的状态信息
[zookeeper, node1]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x6
cversion = 2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
get path watch
注册的监听器在节点内容
发生改变时,向客户端发送通知,注意 Zookeeper 的触发器是一次性的,触发一次后会立即生效。get /node1 watch
## 改变节点数据
set /node1 bbb
## 监听到节点内容改变了
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/node1
stat path watch
注册的监听器能够在节点状态
发生改变时向客户端发出通知。比如节点数据改变、节点被删除等。stat /node2 watch
## 删除节点node2
delete /node2
## 监听器监听到了节点删除
WATCHER::
WatchedEvent state:SyncConnected type:NodeDeleted path:/node2
ls path watch
或者ls2 path watch
注册的监听器,能够监听到该节点下的子节点的增加
和删除
操作。ls /node1 watch
## 创建子节点
create /node1/b b
## 监听到了子节点的新增
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/node1
access control list
访问控制列表可以做到这一点。scheme:id:permission
来标识。
权限模式(scheme)
:授权的策略授权对象(id)
:授权的对象权限(permission)
:授予的权限setACl /node1 ip:192.168.10.1:crdwa
world
:只有一个用户,anyone,表示登录 zookeeper 所有人(默认的模式)。ip
:对客户端使用 IP 地址认证。auth
:使用已添加认证的用户认证。digest
:使用用户名:密码
方式认证。create
、delete
、read
、writer
、admin
。也就是增、删、改、查、管理的权限,简写cdrwa
。delete
是指对子节点的删除权限,其他 4 种权限是对自身节点的操作权限。create
:简写c
,可以创建子节点。delete
:简写d
,可以删除子节点(仅下一级节点)。read
:简写r
,可以读取节点数据以及显示子节点列表。write
:简写w
,可以更改节点数据。admin
:简写a
,可以设置节点访问控制列表权限。getAcl [path]
:读取指定节点的 ACL 权限。setAcl [path] [acl]
:设置 ACLaddauth <scheme> <auth>
:添加认证用户,和 auth,digest 授权模式相关。setAcl [path] world:anyone:[permission]
path
:节点permission
:授予的权限,比如cdrwa
## 获取权限列表(默认的)
getAcl /node2
‘world,‘anyone
: cdrwa
## 去掉读取节点数据的的权限,去掉r
setAcl /node2 world:anyone:cdwa
## 再次获取权限列表
getAcl /node2
‘world,‘anyone
: cdwa
## 获取节点数据,没有权限,失败
get /node2
Authentication is not valid : /node2
setAcl [path] ip:[ip]:[acl]
./zkCli.sh -server ip
192.168.10.1
这个 ip 的增删改查管理的权限。setAcl /node2 ip:192.168.10.1:crdwa
addauth digest [username]:[password]
setAcl [path] auth:[user]:[acl]
chenmou
这个账户添加 cdrwa 权限:## 添加一个认证账户
addauth digest chenmou:123456
## 添加权限
setAcl /node2 auth:chenmou:crdwa
,
分隔。## 创建节点
create /node3
## 添加认证用户
addauth chenmou:123456
## 添加多种授权模式
setAcl /node3 ip:192.178.10.1:crdwa,auth:chenmou:crdwa
super
,该模式提供一个超管可以方便的访问任何权限的节点。super:admin
,需要先为超管生成密码的密文:echo -n super:admin | openssl dgst -binary -sha1 |openssl base64
## 执行完生成了秘钥
xQJmxLMiHGwaqBvst5y6rkB6HQs=
zookeeper
目录下/bin/zkServer.sh
,找到如下一行:nohup JAVA"?Dzookeeper.log.dir=JAVA"?Dzookeeper.log.dir={ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}"
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs=" -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
addauth digest super:admin
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.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.10</version>
</dependency>
//创建CuratorFramework,用来操作api
CuratorFramework client = CuratorFrameworkFactory.builder()
//ip地址+端口号,如果是集群,逗号分隔
.connectString("120.26.101.207:2181")
//会话超时时间
.sessionTimeoutMs(5000)
//超时重试策略,RetryOneTime:超时重连仅仅一次
.retryPolicy(new RetryOneTime(3000))
//命名空间,父节点,如果不指定是在根节点下
.namespace("node4")
.build();
//启动
client.start();
RetryOneTime:
N 秒后重连一次,仅仅一次,演示如下:.retryPolicy(new RetryOneTime(3000))
RetryNTimes
:每 n 秒重连一次,重连 m 次。演示如下://每三秒重连一次,重连3次。arg1:多长时间后重连,单位毫秒,arg2:总共重连几次
.retryPolicy(new RetryNTimes(3000,3))
RetryUntilElapsed
:设置了最大等待时间,如果超过这个最大等待时间将会不再连接。//每三秒重连一次,等待时间超过10秒不再重连。arg1:总等待时间,arg2:多长时间重连,单位毫秒
.retryPolicy(new RetryUntilElapsed(10000,3000))
client.create()
//指定节点的类型。PERSISTENT:持久化节点,PERSISTENT_SEQUENTIAL:持久化有序节点,EPHEMERAL:临时节点,EPHEMERAL_SEQUENTIAL临时有序节点
.withMode(CreateMode.PERSISTENT)
//指定权限列表,OPEN_ACL_UNSAFE:world:anyone:crdwa
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
//写入节点数据,arg1:节点名称 arg2:节点数据
.forPath("/a", "a".getBytes());
withACL(acls)
方法中可以设置自定义的权限列表,代码如下://自定义权限列表
List<ACL> acls=new ArrayList<>();
//指定授权模式和授权对象 arg1:授权模式,arg2授权对象
Id id=new Id("ip","127.0.0.1");
//指定授予的权限,ZooDefs.Perms.ALL:crdwa
acls.add(new ACL(ZooDefs.Perms.ALL,id));
client.create()
.withMode(CreateMode.PERSISTENT)
//指定自定义权限列表
.withACL(acls)
.forPath("/b", "b".getBytes());
creatingParentsIfNeeded()
方法对于创建多层节点,如果其中一个节点不存在的话会自动创建//递归创建节点
client.create()
//递归方法,如果节点不存在,那么创建该节点
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT)
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
//test节点和b节点不存在,递归创建出来
.forPath("/test/a", "a".getBytes());
inBackground()
方法可以异步回调创建节点,创建完成后会自动回调实现的方法 //异步创建节点
client.create()
.withMode(CreateMode.PERSISTENT)
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
//异步创建
.inBackground(new BackgroundCallback() {
/**
* @param curatorFramework 客户端对象
* @param curatorEvent 事件对象
*/
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
//打印事件类型
System.out.println(curatorEvent.getType());
}
})
.forPath("/test1", "a".getBytes());
client.setData()
.forPath("/a","a".getBytes());
client.setData()
//指定版本号更新,如果版本号错误则拒绝更新
.withVersion(1)
.forPath("/a","a".getBytes());
client.setData()
//异步更新
.inBackground(new BackgroundCallback() {
//回调方法
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
}
})
.forPath("/a","a".getBytes());
client.delete()
//删除节点,如果是该节点包含子节点,那么不能删除
.forPath("/a");
client.delete()
//指定版本号删除
.withVersion(1)
//删除节点,如果是该节点包含子节点,那么不能删除
.forPath("/a");
deletingChildrenIfNeeded()
方法client.delete()
//如果删除的节点包含子节点则一起删除
.deletingChildrenIfNeeded()
//删除节点,如果是该节点包含子节点,那么不能删除
.forPath("/a");
inBackground()
client.delete()
.deletingChildrenIfNeeded()
//异步删除节点
.inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
//回调监听
}
})
//删除节点,如果是该节点包含子节点,那么不能删除
.forPath("/a");
byte[] bytes = client.getData().forPath("/node1");
System.out.println(new String(bytes));
//保存节点状态
Stat stat=new Stat();
byte[] bytes = client.getData()
//获取节点状态存储在stat对象中
.storingStatIn(stat)
.forPath("/node1");
System.out.println(new String(bytes));
//获取节点数据的长度
System.out.println(stat.getDataLength());
client.getData()
//异步获取节点数据,回调监听
.inBackground((curatorFramework, curatorEvent) -> {
//节点数据
System.out.println(new String(curatorEvent.getData()));
})
.forPath("/node1");
List<String> strs = client.getChildren().forPath("/");
for (String str:strs) {
System.out.println(str);
}
client.getChildren()
//异步获取
.inBackground((curatorFramework, curatorEvent) -> {
List<String> strs = curatorEvent.getChildren();
for (String str:strs) {
System.out.println(str);
}
})
.forPath("/");
//如果节点不存在,stat为null
Stat stat = client.checkExists().forPath("/node");
//如果节点不存在,stat为null
client.checkExists()
.inBackground((curatorFramework, curatorEvent) -> {
//如果为null则不存在
System.out.println(curatorEvent.getStat());
})
.forPath("/node");
NodeCache
:监听一个特定的节点,监听新增和修改PathChildrenCache
:监听一个节点的子节点,当一个子节点增加、删除、更新时,path Cache 会改变他的状态,会包含最新的子节点的数据和状态。//arg1:连接对象 arg2:监听的节点路径,/namespace/path
final NodeCache nodeCache = new NodeCache(client, "/w1");
//启动监听
nodeCache.start();
//添加监听器
nodeCache.getListenable().addListener(() -> {
//节点路径
System.out.println(nodeCache.getCurrentData().getPath());
//节点数据
System.out.println(new String(nodeCache.getCurrentData().getData()));
});
//睡眠100秒
Thread.sleep(1000000);
//关闭监听
nodeCache.close();
PathChildrenCache
演示://arg1:连接对象 arg2:节点路径 arg3:是否能够获取节点数据
PathChildrenCache cache=new PathChildrenCache(client,"/w1", true);
cache.start();
cache.getListenable().addListener((curatorFramework, pathChildrenCacheEvent) -> {
//节点路径
System.out.println(pathChildrenCacheEvent.getData().getPath());
//节点状态
System.out.println(pathChildrenCacheEvent.getData().getStat());
//节点数据
System.out.println(new String(pathChildrenCacheEvent.getData().getData()));
});
cache.close();
ZK入门指南
。标签:关系 miss gets 同步 自定义 分布式配置 更改 事件 writer
原文地址:https://www.cnblogs.com/Chenjiabing/p/12678607.html