在zookeeper中创建路径的最有效方法,路径的根元素可能存在也可能不存在?

想象一下路径“/ root / child1 / child2 / child3”

想象一下,在动物园管理员中,可能有一部分存在,比如“/ root / child1”

在zookeeper中没有“mkdir -p”的等价物; 此外,如果任何一个操作失败,ZooKeeper.multi()将失败,因此“make path”无法真正被烘焙到多次调用中。 另外,你可以让其他一些客户尝试制作相同的路径……

这就是我为创建路径而想出的。 我想知道是否值得检查一个部件是否存在,以保存exists()调用的往返行程。

//String[] pathParts new String[] { "root", "child1", "child2", "child3" }; public void savePath(String[] pathParts) { if (zooKeeper.exists(pathString, false) != null) return; StringBuilder path = new StringBuilder(); for (String pathElement : pathParts) { path.append(UNIX_FILE_SEPARATOR).append(pathElement); String pathString = path.toString(); try { //bother with the exists call or not? if (zooKeeper.exists(pathString, false) == null) { zooKeeper.create(pathString, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (KeeperException e) { if (e.code() != KeeperException.Code.NODEEXISTS) throw e; } } } 

最有效的方法是什么? 假设a)你不知道有多少路径已经存在,b)其他一些客户端可能正在尝试编写相同的路径(我们希望避免锁定)。

可以通过从服务器到客户端的1次往返来进行存在的呼叫。

创建调用具有相同的往返,但create是一个写操作,需要在zk集群中的服务器之间进行多次往返,因此创建比存在更加昂贵。

所以算法的总时间是,

1读操作的时间*概率节点已存在+(1写操作的时间)*(1 – 节点已存在的概率)。

因此, if(!exist()) create() vs create()都可以更快。 最后它可能没关系。

如果您想要非常快,可以使用async api,这样您就可以创建路径的所有组件,而无需等待服务器逐个响应请求。

 final AtomicBoolean success = new AtomicBoolean(false); final CountdownLatch latch = new CountdownLatch(1); StringCallback cb = new StringCallback() { processResult(int rc, String path, Object ctx, String name) { if(name.equals(pathString ) { //wait for the last path success.set(rc == KeeperException.Code.NODEEXISTS || rc == KeeperException.Code.OK); latch.countDown(); } } }; StringBuilder path = new StringBuilder(); for (String pathElement : pathParts) { path.append(UNIX_FILE_SEPARATOR).append(pathElement); String pathString = path.toString(); //send requests to create all parts of the path without waiting for the //results of previous calls to return zooKeeper.create(pathString, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, cb); } latch.await(); if(!success.get()) { throw ... } 

您可以使用Netflix的curator库,这使得使用zookeeper变得更加简单

 client.create().withMode(CreateMode.PERSISTENT).forPath("/root/child1/child2/child3", new byte[0]).withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE).creatingParentsIfNeeded();