2013-01-11 8 views
17

Durante la lettura dello recipe for lock di ZooKeeper, mi sono confuso. Sembra che questa ricetta per i blocchi distribuiti non possa garantire "" alcuna istantanea nel tempo in cui due client non ritengono di avere lo stesso blocco ". Ma dal momento che ZooKeeper è ampiamente adottato, se ci fossero tali errori nella documentazione di riferimento, qualcuno avrebbe dovuto indicarlo molto tempo fa, quindi cosa ho frainteso?Preoccupazioni per la ricetta di blocco dello zookeeper

Citando the recipe for distributed locks:

Serrature

serrature completamente distribuiti che globalmente sincrono, significato a qualsiasi istantanea in tempo non esistono due clienti pensano tengono la stessa serratura. Questi possono essere implementati usando ZooKeeeper. Come con le code di priorità, prima definire un nodo di blocco.

  1. chiamata a creare() con un percorso di "LockNode/guid-Lock" e la sequenza e le bandiere effimere set.
  2. Chiamare getChildren() sul nodo di blocco senza impostare il flag di controllo (questo è importante per evitare l'effetto herd).
  3. Se il percorso creato nel passaggio 1 ha il suffisso del numero di sequenza più basso, il client ha il blocco e il client esce dal protocollo.
  4. Le chiamate client esiste() con il flag di controllo impostato sul percorso nella directory di blocco con il numero di sequenza successivo più basso.
  5. se esiste() restituisce false, passare al punto 2. In caso contrario, attendere una notifica per il percorso del passaggio precedente prima di passare alla fase 2.

Si consideri il seguente caso:

  • Client1 ha acquisito correttamente il blocco (nel passaggio 3), con il nodo ZooKeeper "locknode/guid-lock-0";
  • Client2 ha creato il nodo "locknode/guid-lock-1", non è riuscito ad acquisire il blocco e ora sta guardando "locknode/guid-lock-0";
  • Successivamente, per qualche motivo (ad esempio, congestione della rete), Client1 non riesce a inviare un messaggio heartbeat al cluster ZooKeeper in tempo, ma Client1 funziona ancora, assumendo erroneamente che sia ancora in possesso del blocco.
  • Ma, ZooKeeper può pensare seduta di Client1 è scaduta, e quindi

    1. delete "LockNode/guid-lock-0",
    2. inviare una notifica al Client2 (o forse inviare la notifica prima?),
    3. ma non è possibile inviare una notifica di "timeout della sessione" a Client1 in tempo (ad esempio, a causa della congestione della rete).
  • Client2 ottiene la notifica, va al passo 2, ottiene l'unico nodo "" LockNode/guid-lock-1" , che essa stessa ha creato,. Quindi, Client2 presuppone che detiene il blocco
  • Ma allo stesso tempo, Client1 presuppone che detenga il blocco

Si tratta di uno scenario valido?

+1

Discussione parallela sulla mailing list _zookeeper-users: http://thread.gmane.org/gmane.comp.java.hadoop.zookeeper.user/5065 – seh

risposta

15

Lo scenario che descrivi potrebbe sorgere. Il Cliente 1 pensa di avere il lucchetto, ma in realtà la sua sessione è scaduta e il Cliente 2 acquisisce il blocco.

La libreria client ZooKeeper informerà il Cliente 1 che la sua connessione è stata disconnessa (ma il client non sa che la sessione è scaduta fino a quando il client si connette al server), quindi il client può scrivere del codice e assumere che il suo il blocco è andato perso se è stato disconnesso troppo a lungo. Ma il thread che utilizza il blocco deve controllare periodicamente che il blocco sia ancora valido, che è intrinsecamente vivace.

+0

grazie; vuol dire che, "l'invariante" - ** in qualsiasi istantanea nel tempo, nessun cliente pensa di tenere lo stesso blocco ** non regge? – hulunbier

+0

corretto – sbridges

+3

Un altro modo semplice per violare l'invariante "a qualsiasi istantanea in tempo" (e quindi dimostrare l'affermazione falsa) è una lunga pausa GC sul client che detiene il blocco. Ad es .: il client C acquisisce il blocco, mentre lo tiene premuto java GC entra in azione e blocca il processo per 60 secondi. Dopo 10 di questi secondi, la sessione C scade e un altro processo acquisisce il blocco. Time 11 è "un'istantanea nel tempo in cui 2 clienti pensano di avere lo stesso blocco". – Marco

0

... Ma, Zookeeper può pensare seduta di client1 è timeouted, e poi ...

Dalla documentazione Zookeeper:

  • La rimozione di un nodo causerà solo un client di svegliarsi dal ogni nodo viene guardato da esattamente un client. In questo modo, si evita l'effetto mandria .
  • Nessun polling o timeout.

Quindi non penso che il problema che descrivi si pone. Mi sembra che possa esserci il rischio di appendere le serrature se succede qualcosa ai clienti che le creano, ma lo scenario che descrivi non dovrebbe sorgere.

+0

grazie; ma non capisco bene la tua idea; per me, "evita l'effetto herd" && "nessun polling o timeout" non può garantire che il client2 non possa acquisire il lock mentre il client1 tiene il lock. Inoltre, il nodo effimero verrà eliminato automaticamente da ZK dopo il timeout della sessione, quindi non posso vedere "il rischio di blocchi appesi" ... – hulunbier

+0

Se la sessione di Client1 è scaduta, il blocco non esiste più in quel caso, ma Client1 ricevere SESSION_EXPIRED o CONNECTION_LOSS dal Zookeeper in quel momento, in modo che sappiano che hanno perso la connettività. – glenatron

+0

E se il messaggio SESSION_EXPIRED non fosse stato inviato al Cliente1 ** in tempo **? A causa della temporanea perdita di pacchetti elevata, ad esempio (la connessione TCP rimane ESTABLISHED) – hulunbier

Problemi correlati