2010-07-27 607 views
4

我拉進ZooKeeper一些併發管理一個項目,我想的第一件事是什麼,對我而言,是很明顯的(使用zkpython綁定):我可以遞歸地在Zookeeper中創建一個路徑嗎?

zh = zookeeper.init('localhost:2181') 
zookeeper.create(zh, '/path/to/a/node', '', [ZOO_OPEN_ACL_UNSAFE]) 

而且我得到了一回NoNodeException因爲我的麻煩。

經過反思和審查文檔(如他們)後,我一直無法找到一種方法來做相當於mkdir -p ZooKeeper將爲我創建丟失的父節點。

我是否缺少任何東西,還是我堅持爲每個部分的路徑發出單獨的create()s,無論我喜歡與否?

+0

我在哪裏可以找到ZOO_OPEN_ACL_UNSAFE? – xitrium 2011-03-23 22:16:03

回答

7

您被困於爲路徑的每個元素分別發出create()。 Zookeeper只有內建的原子操作。遞歸地創建一個路徑不再是原子操作。如果操作在創建一半路徑元素之後掛起,則Zookeeper無法知道您希望如何操作。 我不知道,如果Python中已經有一個Zookeeper助手庫。在java(zkClient)中有一個可以讓你通過多次調用create()來創建遞歸路徑。

+0

到目前爲止,我發現Zookeeper的唯一Python接口是Zookeeper樹中的一個(它只是基本綁定到核心API),所以我想我會編寫自己的便捷方法。 :) 謝謝! – 2010-07-27 16:28:17

2

如果您發出單獨的create(),則在半途中可能會中斷或失敗。要使呼叫原子化,可以使用新的multi() API。請參閱this answer

如果路徑或其中的一部分可能已經存在,那麼在發出下一個命令之前等待每個create()完成將會不必要地緩慢。在這種情況下,您可以使用異步API來加速進程。見this answer

如果你只是想避免額外的電話,你可以使用Netflix's curator庫有一個creatingParentsIfNeeded方法,但請注意,它可能會很慢。見this answer

0
<Code> 

public void updateNode(String path, byte[] data, int version) {  
     try { 
      if (zk.exists(path, this) == `enter code here`null) {    
       createRecursivly(path);    
      } 
      zk.setData(path, data, version); 
     } catch (KeeperException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

    public void createRecursivly(String path){ 
     try {   
      if (zk.exists(path, this) == null && path.length() > 0) { 
       String temp = path.substring(0, path.lastIndexOf("/")); 
       createRecursivly(temp); 
       zk.create(path, null, Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); 
      }else{ 
       return; 
      } 

     } catch (KeeperException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 
</code> 
相關問題