Curator Framework 深入了解
本文受到 colobu 前辈文章的指引,深入了解 Curator Framework 的工作流程,十分感谢 colobu 前辈的博文给予的启发和指导。
ZooKeeper Cache 实现
利用 ZooKeeper 在集群的节点上缓存数据。示例代码
Path Cache
Path Cache 使用 ZK 的节点作为 KV 存储系统,在实现上涉及的类:
PathChildrenCache
PathChildrenCacheEvent
PathChildrenCacheListener
ChildData
PathChildrenCache
是主要类,他的构造方法是
public PathChildrenCache(CuratorFramework client,
String path,
boolean cacheData /*是否缓存node,会缓存在一个 ConcurrentHashMap内*/)
比较奇特的是,设计上PathChildrenCache
只负责获取数据,也就是只有 list
、get
的操作,并没有 set
、 remove
操作,需要新增数据之类的都是统一通过 CuratorFramework
构造出的 client 去做对应操作(任何对 zk 节点完成增删的操作都可)。PathChildrenCache
通过对构造函数中填入的 PATH 路径进行监听,这里有两个 Watcher,childrenWatcher
负责监听节点的增加,dataWatcher
负责监听节点数据的改动和节点的删除。
构造好一个 PathChildrenCache
后需要 start()
后才能正常使用,调用 close()来结束使用。start()
方法中也可以传入 StartMode
,用来为初始的 cache 设置暖场方式(warm):
NORMAL
: 初始时为空。BUILD_INITIAL_CACHE
: 在这个方法返回之前调用rebuild()
,此方法会将 ZK 的节点 kv 存到本地缓存(ConcurrentHashMap
)内。POST_INITIALIZED_EVENT
: 当Cache初始化数据后发送一个PathChildrenCacheEvent.Type#INITIALIZED
事件
获取当前的 Cache 值可以使用如下方法:
// PathChildrenCache.class
// 获取所有的缓存数据
public List<ChildData> getCurrentData() {
return ImmutableList.copyOf(Sets.<ChildData>newTreeSet(currentData/*这就是本地缓存 concurrentHashMap*/.values()));
}
// 获取指定 PATH 下的缓存数据(实际就是用 key)
public ChildData getCurrentData(String fullPath) {
return currentData/*这就是本地缓存 concurrentHashMap*/.get(fullPath);
}
可以增加 listener 监听缓存变化:
/*
这里的 Listener 就是 PathChildrenCacheListener 的实例,据此新建自己的监听器。
*/
cache/*PathChildrenCache 的实例*/.getListenable().addListener(listener);
Node Cache
Node Cache 顾名思义就是只对一个 Node 节点做监控,涉及到下面的三个类:
- NodeCache
- NodeCacheListener
- ChildData
Node Cache 在更新数据的时候并不是同步的,也就意味着并发修改数据返回意料之外的结果。使用这个缓存的时候需要自己多加注意。具体的使用方法同 Path Cache,只是 Node Cache 的 getCurrentData()
只会返回一个 ChildData 了。
Tree Node
Tree Node 既可以监控节点的状态,也监控节点的子节点的状态。涉及到下面四个类:
- TreeCache
- TreeCacheListener
- TreeCacheEvent
- ChildData
TreeCache 使用 Builder 模式来构造:
// TreeCache.Builder.class
private Builder(CuratorFramework client, String path){
this.client = checkNotNull(client);
this.path = validatePath(path);
}
// 构造出来一个 builder 后可以配置
private boolean cacheData = true;
private boolean dataIsCompressed = false;
private ExecutorService executorService = null;
private int maxDepth = Integer.MAX_VALUE;
private boolean createParentNodes = false;
TreeCache 也可以使用 getCurrentChildren(String path)
方法获取 path 下一级的所有的 kv 对。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 [email protected]