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 只负责获取数据,也就是只有 listget 的操作,并没有 setremove 操作,需要新增数据之类的都是统一通过 CuratorFramework 构造出的 client 去做对应操作(任何对 zk 节点完成增删的操作都可)。PathChildrenCache 通过对构造函数中填入的 PATH 路径进行监听,这里有两个 Watcher,childrenWatcher 负责监听节点的增加,dataWatcher负责监听节点数据的改动和节点的删除。
构造好一个 PathChildrenCache 后需要 start() 后才能正常使用,调用 close()来结束使用。start() 方法中也可以传入 StartMode,用来为初始的 cache 设置暖场方式(warm):

  1. NORMAL: 初始时为空。
  2. BUILD_INITIAL_CACHE: 在这个方法返回之前调用rebuild(),此方法会将 ZK 的节点 kv 存到本地缓存(ConcurrentHashMap)内。
  3. 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]