一、应用
1.ZK有什么用
zk维护了一个树形结构,每个节点都可以存储一些数据,其中包含了Leader,Follower,Observer三个角色;
2.ZK数据一致性处理
2.1 zab协议(Zookeeper Atomic Broadcast )
- 在图中只有当ACK过半的时候才会创建节点,也就是才会commit;
- 如果client不是链接的Leader那么其他节点接收请求后会转发请求给Leader
- 如果Follower节点越多会影响写的性能,但是添加Observer不会他可以提升读的性能应为他不参加投票但可以读
3.ZK节点类型
- 持久节点
- 节点内容限制1M
- ·create /data “data”·
- 临时节点
- 临时节点是session过期就直接没了,注意此处和connection有区别,在命令行通过quit命令关闭命令窗口就相当于session失效, 但是如果直接crtl + c是不行的; 因为直接crtl + c此时的session没有被正常关闭还是处于存活的,所以再次进入zk还是能看到临时数据,但过一会儿就看不到了因为在没有心跳的情况下session的到期时间到了,数据也被销毁了
- 临时节点下面是不能创建任何子节点的
create -e /data "data"
- 持久顺序节点
- ·create -s /data/seq_ 1·
- 顺序节点额含义就是当前创建命令可以执行多次,zk会自动的在seq_后面加上数字如:seq_0,seq_1,seq_2
- 临时顺序节点
- session
- 在client链接到Server的时候在Server会创建一个session, 并且当前session是有到期时间的,服务端也在做倒计时;只有客户端和服务端再次产生心跳之后倒计时会重新刷新
4. zk节点CRUD
- create [-s|-e] /node data
- delete/rmr /node
- set /node data
- get /node
5.zk的ACL
- zk的权限是基于节点的,并且子节点不会继承父节点的权限;也就是客户端不能访问父节点但是能访问字节点
- 获取ACL命令:
getAcl /node
5.1节点权限设置
-
命令:
setAcl /node shcema:id:permission
-
schema:
- world: 代表了所有人的意思,所以id只有anyone
- ip: 代表使用ip地址认证
- auth:使用已添加的认证用户认证
- digest: 使用“用户名:密码"方式认证
-
id
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nBV23rXm-1584110164303)(en-resource://database/623:1)] -
权限
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YkKqRbVP-1584110164304)(en-resource://database/625:1)]
6.Watch
- 原生zookeeper客户端:可以在getData的时候设置Watch,注意这种监听是一次性的,只会监听一次
ZooKeeper zooKeeper = new ZooKeeper("localhost:2181", 5000,
new Watcher() {
public void process(WatchedEvent watchedEvent) {
System.out.println("连接时" + watchedEvent);
}
});
zooKeeper.getData("/data", new Watcher() {
public void process(WatchedEvent watchedEvent) {
//监听节点改变
if (Event.EventType.NodeDataChanged.equals(watchedEvent.getType())) {
}
}
}, new Stat());
- curator客户端,他的监听可以多次监听
7. zookeeper应用
-
发布订阅(分布式配置中心)
-
统一命名服务(分布式id,利用顺序节点)
-
Master的选举
- 此处直接所有机器创建一个节点成功的就是Master不成功过的就监听节点变化;如果节点没了就在此抢占Master节点
-
分布式锁
- 排它锁:同样是采用创建临时节点的方式
- 共享锁: 临时顺序节点实现
- 创建节点之后获取所有子节点,判断比自己小的节点是否全部是读是的就直接回去了读锁;如果想要写就等前面的锁全部是放了才能是写锁
-
分布式队列
- 这个队列相当于客户端自己把自己添加到队列中,同样是利用的顺序临时节点,判断自己当前是否为最小的节点,是的就可以执行任务了(FIFO队列)
-
分布式屏障(类似CountDownLatch)
- 一个父节点存储一个数字N, 每来一个节点就创建一个临时节点,并获取所有子节点列表看是否有N个有了就可以继续执行后续任务了;没有就注册子节点列表的监听重复以上步骤
二、zookeeper源码分析
1. zkClient.sh脚本做了什么?
- 在一下脚本中我们可以发现,脚本实质是运行了java命令,主要的类就是org.apache.zookeeper.ZooKeeperMain这个类; 从构造方法往里面看可以发现zk使用的NIO来进行通信
ZOOBIN="${BASH_SOURCE-$0}"
ZOOBIN="$(dirname "${ZOOBIN}")"
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"
if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
. "$ZOOBINDIR"/../libexec/zkEnv.sh
else
. "$ZOOBINDIR"/zkEnv.sh
fi
"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
-cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS \
org.apache.zookeeper.ZooKeeperMain "$@"