2012-03-27 32 views
10

想象一下,一個路徑 「/根/ child1 /的child2/child3」在zookeeper中創建路徑的最有效方法,其中路徑的根元素可能存在也可能不存在?

試想一下,動物園管理員,也許這項工作的一部分存在,說 「/根/ child1」

不存在「的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)某個其他客戶端可能正在嘗試寫入相同的路徑(並且我們希望避免鎖定)。

+0

的請求響應1你能舉例說明實例變量路徑包含什麼以及傳遞給pathParts參數的內容?將代碼作爲追溯到自身的路徑有點困惑。 – 2012-03-28 00:46:12

+0

對不起 - 有一些錯誤。現在修正,或多或少。 – marathon 2012-03-28 01:47:48

回答

7

一個存在的呼叫可以用1周從服務器到客戶端的行程進行。

創建調用具有相同的往返行程,但創建是一個寫入操作,需要zk集羣中服務器之間的更多往返行程,因此創建存在的成本要稍高一些。

所以對於你的算法的總時間,

時間爲1閱讀OP *概率節點已經存在+(時間爲1個寫操作)*(1 - 概率節點已經存在)。

因此,無論是if(!exist()) create()還是create()都可能會更快。最後它可能沒有關係。

如果你想成爲真快,你可以使用異步API,以便您可以創建路徑的所有組件,而不必等待服務器由1

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 ... 
} 
+0

好的答案。 +1 – kirugan 2016-07-23 21:51:53

13

您可以使用它使得使用飼養員要簡單得多Netflix's curator

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

但是這比上面更高效,還是隻是隱藏它? – marathon 2012-03-29 03:04:32

+0

查看EnsurePath(https://github.com/Netflix/curator/blob/master/curator-client/src/main/java/com/netflix/curator/utils/EnsurePath.java)和ZKPaths(https: //github.com/Netflix/curator/blob/master/curator-client/src/main/java/com/netflix/curator/utils/ZKPaths.java)並自行決定 – 2012-03-29 04:46:05

+0

相同數量的網絡通話,但更糟的是因爲他們有一個同步塊。我打算與動物園人員打開一張票,要求他們進行原子路徑創建調用。 – marathon 2012-03-29 18:19:09

相關問題