2010-07-27 4 views
4

Je tirais ZooKeeper dans un projet pour une gestion de la concurrence, et la première chose que j'ai essayé était quelque chose qui, pour moi, était tout à fait évident (en utilisant la zkpython de liaison):Puis-je créer récursivement un chemin dans Zookeeper?

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

Et je suis revenu un NoNodeException pour mes ennuis. Après avoir réfléchi à cela et revu les documents (tels qu'ils sont), j'ai été incapable de trouver un moyen de faire l'équivalent d'un mkdir -p où ZooKeeper va créer les nœuds parent manquants pour moi. Est-ce que je manque quelque chose, ou est-ce que je suis juste coincé en émettant des create() séparés pour chaque partie d'un chemin, que cela me plaise ou non?

+0

Où puis-je trouver ZOO_OPEN_ACL_UNSAFE? – xitrium

Répondre

7

Vous êtes bloqué pour émettre des create() distincts pour chaque élément du chemin. Zookeeper n'a que des opérations atomiques intégrées. Créer un chemin de manière récursive n'est plus une opération atomique. Zookeeper ne pouvait pas savoir, ce que vous voulez qu'il fasse, si l'opération se bloque après avoir créé la moitié des éléments du chemin. Je ne sais pas s'il y a déjà une bibliothèque d'aide Zookeeper en python. Il y en a un dans java (zkClient) qui vous permettra de créer des chemins récursifs en appelant plusieurs fois create().

+0

Jusqu'à présent, la seule interface Python que j'ai trouvée pour Zookeeper est celle de l'arborescence de Zookeeper (qui est juste une liaison de base à l'API principale), donc j'imagine que j'écrirai mes propres méthodes de commodité. :) Merci! –

2

Si vous créez des create() distincts, vous risquez d'être interrompu ou d'échouer à mi-parcours. Pour rendre l'appel atomique, vous pouvez utiliser le nouveau multi() API. Voir this answer.

Si le chemin ou une partie de celui-ci peut déjà exister, attendre que chaque create() se termine avant d'émettre le suivant soit inutilement lent. Dans ce cas, vous pouvez utiliser l'API asynchrone pour accélérer le processus. Voir this answer.

Si vous voulez juste éviter les appels supplémentaires, vous pouvez utiliser la bibliothèque Netflix's curator qui a une méthode creatingParentsIfNeeded, mais sachez qu'elle peut être lente. Voir this answer.

0

Kazoo has an ensure_path(path) operation, bien qu'elle ne soit pas considérée comme atomique. En utilisant cela, vous économiserez au moins le besoin d'écrire votre propre code pour une création récursive.

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> 
Questions connexes