"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Ti suggerisco di leggere la trascrizione della conferenza "Hadoop. ZooKeeper" dalla serie "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Cos'è ZooKeeper, il suo posto nell'ecosistema Hadoop. False verità sul calcolo distribuito. Schema di un sistema distribuito standard. Difficoltà nel coordinare i sistemi distribuiti. Tipici problemi di coordinazione. I principi alla base della progettazione di ZooKeeper. Modello dati ZooKeeper. flag di znode. Sessioni. API client. Primitive (configurazione, appartenenza a gruppi, lock semplici, elezione del leader, lock senza effetto gregge). Architettura di ZooKeeper. DB ZooKeeper. ZAB. Gestore della richiesta.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Oggi parleremo di ZooKeeper. Questa cosa è molto utile. Come ogni prodotto Apache Hadoop, ha un logo. Raffigura un uomo.

Prima di ciò, abbiamo parlato principalmente di come i dati possono essere elaborati lì, di come archiviarli, cioè di come utilizzarli in qualche modo e lavorarci in qualche modo. E oggi vorrei parlare un po' della creazione di applicazioni distribuite. E ZooKeeper è una di quelle cose che ti permette di semplificare la questione. Questo è un tipo di servizio destinato a una sorta di coordinamento dell'interazione dei processi nei sistemi distribuiti, nelle applicazioni distribuite.

La necessità di tali applicazioni diventa ogni giorno sempre maggiore, ecco di cosa tratta il nostro corso. Da un lato, MapReduce e questo framework già pronto consentono di livellare questa complessità e liberare il programmatore dalla scrittura di primitive come l'interazione e il coordinamento dei processi. Ma d'altra parte nessuno garantisce che ciò non dovrà comunque essere fatto. MapReduce o altri framework già pronti non sempre sostituiscono completamente alcuni casi che non possono essere implementati utilizzando questo. Incluso lo stesso MapReduce e un sacco di altri progetti Apache; anche loro, infatti, sono applicazioni distribuite. E per facilitare la scrittura, hanno scritto ZooKeeper.

Come tutte le applicazioni relative a Hadoop, è stata sviluppata da Yahoo! Ora è anche un'applicazione ufficiale Apache. Non è sviluppato così attivamente come HBase. Se vai su JIRA HBase, ogni giorno ci sono un sacco di segnalazioni di bug, un sacco di proposte per ottimizzare qualcosa, ad es. la vita nel progetto va avanti costantemente. E ZooKeeper, da un lato, è un prodotto relativamente semplice e, dall'altro, questo ne garantisce l'affidabilità. Ed è abbastanza facile da usare, motivo per cui è diventato uno standard nelle applicazioni all'interno dell'ecosistema Hadoop. Quindi ho pensato che sarebbe stato utile recensirlo per capire come funziona e come utilizzarlo.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Questa è una foto di una lezione che abbiamo avuto. Possiamo dire che è ortogonale a tutto quello che abbiamo considerato finora. E tutto ciò che viene indicato qui, in un modo o nell'altro, funziona con ZooKeeper, ovvero è un servizio che utilizza tutti questi prodotti. Né HDFS né MapReduce scrivono i propri servizi simili che funzionerebbero specificamente per loro. Di conseguenza, viene utilizzato ZooKeeper. E questo semplifica lo sviluppo e alcune cose legate agli errori.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Da dove viene tutto questo? Sembrerebbe che abbiamo lanciato due applicazioni in parallelo su computer diversi, le abbiamo collegate con una stringa o in una mesh e tutto funziona. Ma il problema è che la rete è inaffidabile e se annusate il traffico o guardate cosa sta succedendo lì a basso livello, come i client interagiscono sulla rete, spesso potete vedere che alcuni pacchetti vengono persi o inviati nuovamente. Non per niente sono stati inventati i protocolli TCP, che consentono di stabilire una determinata sessione e garantire la consegna dei messaggi. Ma in ogni caso, anche il TCP non sempre può salvarti. Tutto ha un timeout. La rete potrebbe semplicemente interrompersi per un po'. Potrebbe semplicemente lampeggiare. E tutto ciò porta al fatto che non puoi fare affidamento sull'affidabilità della rete. Questa è la differenza principale rispetto alla scrittura di applicazioni parallele che vengono eseguite su un computer o su un supercomputer, dove non esiste una rete, dove è presente un bus di scambio dati più affidabile in memoria. E questa è una differenza fondamentale.

Tra l'altro nell'utilizzo della Rete c'è sempre una certa latenza. Anche il disco ce l'ha, ma la Rete ne ha di più. La latenza è un tempo di ritardo, che può essere piccolo o piuttosto significativo.

La topologia della rete sta cambiando. Cos'è la topologia: questo è il posizionamento delle nostre apparecchiature di rete. Ci sono data center, ci sono rack che stanno lì, ci sono candele. Tutto questo può essere ricollegato, spostato, ecc. Anche tutto questo deve essere preso in considerazione. Cambiano i nomi IP, cambia il routing attraverso il quale viaggia il nostro traffico. Anche questo deve essere preso in considerazione.

La rete potrebbe cambiare anche in termini di apparecchiature. Dalla pratica, posso dire che ai nostri ingegneri di rete piace molto aggiornare periodicamente qualcosa sulle candele. All'improvviso è uscito un nuovo firmware e non erano particolarmente interessati ad alcuni cluster Hadoop. Hanno il loro lavoro. Per loro l’importante è che la Rete funzioni. Di conseguenza, vogliono ricaricare qualcosa lì, eseguire un flashing sul proprio hardware e anche l'hardware cambia periodicamente. Tutto ciò in qualche modo deve essere preso in considerazione. Tutto ciò influisce sulla nostra applicazione distribuita.

Di solito le persone che iniziano a lavorare con grandi quantità di dati per qualche motivo credono che Internet sia senza limiti. Se è presente un file di diversi terabyte, puoi portarlo sul tuo server o computer e aprirlo utilizzando gatto e guarda. C'è un altro errore Vim guarda i log. Non farlo mai perché è brutto. Perché Vim cerca di bufferizzare tutto, di caricare tutto in memoria, specialmente quando iniziamo a muoverci attraverso questo registro e cercare qualcosa. Queste sono cose che sono state dimenticate, ma che vale la pena considerare.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

È più semplice scrivere un programma che venga eseguito su un computer con un processore.

Quando il nostro sistema cresce, vogliamo parallelizzarlo tutto e parallelizzarlo non solo su un computer, ma anche su un cluster. La domanda sorge spontanea: come coordinare questa questione? Forse le nostre applicazioni non interagiscono nemmeno tra loro, ma abbiamo eseguito diversi processi in parallelo su più server. E come monitorare che tutto vada bene per loro? Ad esempio, inviano qualcosa su Internet. Devono scrivere il loro stato da qualche parte, ad esempio in una sorta di database o registro, quindi aggregare questo registro e quindi analizzarlo da qualche parte. Inoltre, dobbiamo tenere conto del fatto che il processo funzionava e funzionava, all'improvviso è apparso un errore o si è bloccato, quindi quanto velocemente lo scopriremo?

È chiaro che tutto ciò può essere rapidamente monitorato. Anche questo è positivo, ma il monitoraggio è una cosa limitata che ti consente di monitorare alcune cose al massimo livello.

Quando vogliamo che i nostri processi inizino a interagire tra loro, ad esempio per scambiarsi alcuni dati, sorge anche la domanda: come accadrà? Ci sarà una sorta di race condition, si sovrascriveranno a vicenda, i dati arriveranno correttamente, si perderà qualcosa lungo il percorso? Dobbiamo sviluppare una sorta di protocollo, ecc.

Il coordinamento di tutti questi processi non è una cosa banale. E costringe lo sviluppatore a scendere a un livello ancora più basso e scrivere sistemi da zero o non proprio da zero, ma non è così semplice.

Se trovi un algoritmo crittografico o addirittura lo implementi, buttalo via immediatamente, perché molto probabilmente non funzionerà per te. Molto probabilmente conterrà una serie di errori che hai dimenticato di fornire. Non usarlo mai per qualcosa di serio perché molto probabilmente sarà instabile. Perché tutti gli algoritmi esistenti sono stati testati dal tempo per molto tempo. È infastidito dalla comunità. Questo è un argomento separato. Ed è lo stesso qui. Se è possibile non implementare da soli una sorta di sincronizzazione del processo, allora è meglio non farlo, perché è piuttosto complicato e ti porta lungo il percorso traballante della costante ricerca di errori.

Oggi parliamo di ZooKeeper. Da un lato è un framework, dall'altro è un servizio che semplifica la vita allo sviluppatore e semplifica il più possibile l'implementazione della logica e il coordinamento dei nostri processi.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Ricordiamo come potrebbe apparire un sistema distribuito standard. Questo è ciò di cui abbiamo parlato: HDFS, HBase. Esiste un processo Master che gestisce i processi lavoratori e slave. È responsabile del coordinamento e della distribuzione dei compiti, del riavvio dei lavoratori, del lancio di nuovi e della distribuzione del carico.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Una cosa più avanzata è il servizio di coordinamento, ovvero spostare l'attività di coordinamento stessa in un processo separato, oltre a eseguire una sorta di backup o master stanby in parallelo, poiché il master potrebbe non funzionare. E se il Maestro cade, il nostro sistema non funzionerà. Stiamo eseguendo il backup. Alcuni affermano che il Master deve essere replicato per il backup. Anche questo può essere affidato al Servizio di Coordinamento. Ma in questo diagramma è il Master stesso ad essere responsabile del coordinamento dei lavoratori; qui è il servizio a coordinare le attività di replica dei dati.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Un'opzione più avanzata è quando tutto il coordinamento viene gestito dal nostro servizio, come avviene di solito. Si assume la responsabilità di assicurarsi che tutto funzioni. E se qualcosa non funziona, lo scopriamo e cerchiamo di aggirare questa situazione. In ogni caso ci ritroviamo con un Master che in qualche modo interagisce con gli slave e può inviare dati, informazioni, messaggi, ecc. attraverso qualche servizio.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Esiste uno schema ancora più avanzato, quando non abbiamo un Master, tutti i nodi sono master-slave, diversi nel loro comportamento. Ma devono ancora interagire tra loro, quindi rimane ancora qualche servizio per coordinare queste azioni. Probabilmente Cassandra, che funziona secondo questo principio, si adatta a questo schema.

È difficile dire quale di questi schemi funzioni meglio. Ognuno ha i suoi pro e contro.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

E non c'è bisogno di aver paura di alcune cose con il Maestro, perché, come dimostra la pratica, non è così suscettibile al servizio costante. La cosa principale qui è scegliere la soluzione giusta per ospitare questo servizio su un potente nodo separato, in modo che disponga di risorse sufficienti, in modo che, se possibile, gli utenti non abbiano accesso lì, in modo che non interrompano accidentalmente questo processo. Ma allo stesso tempo, in uno schema del genere è molto più semplice gestire i lavoratori dal processo Master, ad es. questo schema è più semplice dal punto di vista dell'implementazione.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

E questo schema (sopra) è probabilmente più complesso, ma più affidabile.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Il problema principale sono i fallimenti parziali. Ad esempio, quando inviamo un messaggio in rete, si verifica qualche tipo di incidente e colui che ha inviato il messaggio non saprà se il suo messaggio è stato ricevuto e cosa è successo dal lato del destinatario, non saprà se il messaggio è stato elaborato correttamente , cioè non riceverà alcuna conferma.

Di conseguenza, dobbiamo elaborare questa situazione. E la cosa più semplice è inviare nuovamente questo messaggio e attendere finché non riceviamo una risposta. In questo caso non viene preso in considerazione se lo stato del ricevitore è cambiato. Potremmo inviare un messaggio e aggiungere gli stessi dati due volte.

ZooKeeper offre modi per gestire tali rifiuti, il che semplifica anche la nostra vita.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Come accennato in precedenza, questo è simile alla scrittura di programmi multi-thread, ma la differenza principale è che nelle applicazioni distribuite che costruiamo su macchine diverse, l'unico modo per comunicare è la rete. Essenzialmente, questa è un’architettura senza nulla condiviso. Ogni processo o servizio eseguito su una macchina ha la propria memoria, il proprio disco, il proprio processore, che non condivide con nessuno.

Se scriviamo un programma multi-thread su un computer, possiamo utilizzare la memoria condivisa per scambiare dati. Abbiamo un cambio di contesto lì, i processi possono cambiare. Ciò influisce sulle prestazioni. Da un lato non esiste nulla del genere nel programma sul cluster, ma ci sono problemi con la rete.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Di conseguenza, i problemi principali che sorgono quando si scrivono sistemi distribuiti sono la configurazione. Stiamo scrivendo una sorta di applicazione. Se è semplice, allora codifichiamo tutti i tipi di numeri nel codice, ma questo è scomodo, perché se decidiamo che invece di un timeout di mezzo secondo vogliamo un timeout di un secondo, allora dobbiamo ricompilare l'applicazione e stendere di nuovo tutto. Una cosa è quando è su una macchina, quando puoi semplicemente riavviarlo, ma quando abbiamo molte macchine, dobbiamo copiare costantemente tutto. Dobbiamo cercare di rendere l'applicazione configurabile.

Qui stiamo parlando di configurazione statica per i processi di sistema. Questo non è del tutto, forse dal punto di vista del sistema operativo potrebbe essere una configurazione statica per i nostri processi, cioè questa è una configurazione che non può essere semplicemente presa e aggiornata.

Esiste anche una configurazione dinamica. Questi sono i parametri che vogliamo modificare al volo in modo che vengano ripresi lì.

Qual è il problema qui? Abbiamo aggiornato la configurazione, l'abbiamo implementata, e allora? Il problema potrebbe essere che da un lato abbiamo lanciato la configurazione, ma ci siamo dimenticati della novità, la configurazione è rimasta lì. In secondo luogo, durante il lancio, la configurazione è stata aggiornata in alcuni punti, ma non in altri. E alcuni processi della nostra applicazione eseguiti su una macchina sono stati riavviati con una nuova configurazione e da qualche parte con una vecchia. Ciò può comportare che la nostra applicazione distribuita sia incoerente dal punto di vista della configurazione. Questo problema è comune. Per una configurazione dinamica, è più rilevante perché implica che possa essere modificata al volo.

Un altro problema è l’appartenenza al gruppo. Abbiamo sempre qualche gruppo di lavoratori, vogliamo sempre sapere quale di loro è vivo, quale di loro è morto. Se è presente un Master, deve capire quali lavoratori possono essere reindirizzati ai client in modo che eseguano calcoli o lavorino con i dati e quali no. Un problema che si pone costantemente è che dobbiamo sapere chi lavora nel nostro cluster.

Un altro problema tipico sono le elezioni dei leader, quando vogliamo sapere chi comanda. Un esempio è la replica, quando abbiamo un processo che riceve operazioni di scrittura e poi le replica tra altri processi. Sarà lui il leader, tutti gli altri gli obbediranno, lo seguiranno. È necessario scegliere un processo in modo che sia inequivocabile per tutti, in modo che non risulti che vengono selezionati due leader.

Esiste anche un accesso mutuamente esclusivo. Il problema qui è più complesso. Esiste un mutex quando si scrivono programmi multi-thread e si desidera che l'accesso a qualche risorsa, ad esempio una cella di memoria, sia limitato ed eseguito da un solo thread. Qui la risorsa potrebbe essere qualcosa di più astratto. E diverse applicazioni provenienti da diversi nodi della nostra rete dovrebbero ricevere solo l'accesso esclusivo a una determinata risorsa e non in modo che tutti possano modificarla o scrivere qualcosa lì. Queste sono le cosiddette serrature.

ZooKeeper ti consente di risolvere tutti questi problemi in un modo o nell'altro. E mostrerò con esempi come ti permette di farlo.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Non sono presenti primitive di blocco. Quando iniziamo a utilizzare qualcosa, questa primitiva non attenderà che si verifichi alcun evento. Molto probabilmente, questa cosa funzionerà in modo asincrono, consentendo così ai processi di non bloccarsi mentre aspettano qualcosa. Questa è una cosa molto utile.

Tutte le richieste del client vengono elaborate nell'ordine della coda generale.

E i clienti hanno l'opportunità di ricevere notifiche sui cambiamenti in alcuni stati, sui cambiamenti nei dati, prima che il cliente stesso veda i dati modificati.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

ZooKeeper può funzionare in due modalità. Il primo è autonomo, su un nodo. Questo è utile per i test. Può anche funzionare in modalità cluster su qualsiasi numero di server. Se abbiamo un cluster di 100 macchine, non è necessario che funzioni su 100 macchine. È sufficiente selezionare diverse macchine su cui è possibile eseguire ZooKeeper. E professa il principio dell'alta disponibilità. Su ogni istanza in esecuzione, ZooKeeper memorizza un'intera copia dei dati. Più tardi ti dirò come fa. Non suddivide i dati né li partiziona. Da un lato è un aspetto negativo il fatto che non possiamo immagazzinare molto, dall'altro non è necessario farlo. Non è progettato per questo, non è un database.

I dati possono essere memorizzati nella cache sul lato client. Questo è un principio standard per non interrompere il servizio e non caricarlo con le stesse richieste. Un client intelligente di solito lo sa e lo memorizza nella cache.

Qui, ad esempio, qualcosa è cambiato. C'è una sorta di applicazione. È stato eletto un nuovo leader, responsabile, ad esempio, dell'elaborazione delle operazioni di scrittura. E vogliamo replicare i dati. Una soluzione è metterlo in loop. E mettiamo costantemente in discussione il nostro servizio: è cambiato qualcosa? La seconda opzione è più ottimale. Questo è un meccanismo di controllo che ti consente di avvisare i clienti che qualcosa è cambiato. Questo è un metodo meno costoso in termini di risorse e più conveniente per i clienti.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Il cliente è l'utente che utilizza ZooKeeper.

Il server è il processo ZooKeeper stesso.

Znode è la cosa fondamentale in ZooKeeper. Tutti gli znodi sono archiviati in memoria da ZooKeeper e sono organizzati sotto forma di diagramma gerarchico, sotto forma di albero.

Esistono due tipi di operazioni. Il primo è aggiornamento/scrittura, quando qualche operazione cambia lo stato del nostro albero. L'albero è comune.

Ed è possibile che il client non completi una richiesta e venga disconnesso, ma possa stabilire una sessione attraverso la quale interagisce con ZooKeeper.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Il modello dati di ZooKeeper assomiglia a un file system. C'è una radice standard e poi abbiamo esaminato le directory che vanno dalla radice. E poi il catalogo di primo livello, di secondo livello. Questo è tutto znodes.

Ogni znode può memorizzare alcuni dati, solitamente non molto grandi, ad esempio 10 kilobyte. E ogni znode può avere un certo numero di figli.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Gli Znodi sono disponibili in diversi tipi. Possono essere creati. E quando creiamo uno znode, specifichiamo il tipo a cui dovrebbe appartenere.

Ci sono due tipi. La prima è la bandiera effimera. Znode vive all'interno di una sessione. Ad esempio, il client ha stabilito una sessione. E finché questa sessione sarà viva, esisterà. Ciò è necessario per non produrre qualcosa di non necessario. Questo è adatto anche per i momenti in cui è importante per noi memorizzare i dati primitivi all'interno di una sessione.

Il secondo tipo è il flag sequenziale. Incrementa il contatore nel percorso verso lo znode. Ad esempio, avevamo una directory con l'applicazione 1_5. E quando abbiamo creato il primo nodo, ha ricevuto p_1, il secondo - p_2. E quando chiamiamo questo metodo ogni volta, passiamo il percorso completo, indicando solo una parte del percorso, e questo numero viene automaticamente incrementato perché indichiamo il tipo di nodo: sequenziale.

Znodo regolare. Vivrà sempre e avrà il nome che le diciamo.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Un'altra cosa utile è la bandiera dell'orologio. Se lo installiamo, il client può iscriversi ad alcuni eventi per un nodo specifico. Ti mostrerò più tardi con un esempio come è possibile farlo. ZooKeeper stesso notifica al client che i dati sul nodo sono cambiati. Tuttavia, le notifiche non garantiscono che siano arrivati ​​alcuni nuovi dati. Dicono semplicemente che qualcosa è cambiato, quindi devi comunque confrontare i dati in seguito con chiamate separate.

E come ho già detto, l'ordine dei dati è determinato in kilobyte. Non è necessario archiviare lì dati di testo di grandi dimensioni, perché non è un database, è un server di coordinamento delle azioni.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Ti parlerò un po’ delle sessioni. Se disponiamo di più server, possiamo spostarci in modo trasparente da un server all'altro utilizzando l'identificatore di sessione. È abbastanza conveniente.

Ogni sessione ha una sorta di timeout. Una sessione è definita dal fatto che il client invii qualcosa al server durante quella sessione. Se non ha trasmesso nulla durante il timeout, la sessione si interrompe oppure il client può chiuderla da solo.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Non ha molte funzionalità, ma puoi fare diverse cose con questa API. La chiamata che abbiamo visto create crea uno znode e accetta tre parametri. Questo è il percorso dello znode e deve essere specificato per intero dalla radice. E anche questi sono alcuni dati che vogliamo trasferire lì. E il tipo di bandiera. E dopo la creazione restituisce il percorso allo znode.

In secondo luogo, puoi eliminarlo. Il trucco qui è che il secondo parametro, oltre al percorso dello znode, può specificare la versione. Di conseguenza, quello znode verrà eliminato se la sua versione che abbiamo trasferito è equivalente a quella realmente esistente.

Se non vogliamo controllare questa versione, passiamo semplicemente l'argomento "-1".

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

In terzo luogo, verifica l'esistenza di uno znode. Restituisce vero se il nodo esiste, falso altrimenti.

E poi appare il flag watch, che ti consente di monitorare questo nodo.

Puoi impostare questo flag anche su un nodo inesistente e ricevere una notifica quando appare. Anche questo può essere utile.

Ci sono un paio di altre sfide getData. È chiaro che possiamo ricevere dati tramite znode. Puoi anche usare il flag watch. In questo caso, non verrà installato se non è presente alcun nodo. Pertanto, è necessario capire che esiste e quindi ricevere i dati.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

C'è anche ImpostaDati. Qui passiamo alla versione. E se lo trasmettiamo, i dati sullo znode di una determinata versione verranno aggiornati.

Puoi anche specificare "-1" per escludere questo controllo.

Un altro metodo utile è getChildren. Possiamo anche ottenere un elenco di tutti gli znodi che ne fanno parte. Possiamo monitorarlo impostando il flag watch.

E metodo sync consente di inviare tutte le modifiche contemporaneamente, garantendo così che vengano salvate e che tutti i dati siano stati completamente modificati.

Se tracciamo analogie con la programmazione normale, quando usi metodi come write, che scrivono qualcosa su disco e dopo averti restituito una risposta, non vi è alcuna garanzia di aver scritto i dati su disco. E anche quando il sistema operativo è sicuro che tutto sia stato scritto, nel disco stesso esistono meccanismi in cui il processo passa attraverso strati di buffer e solo dopo i dati vengono inseriti sul disco.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Vengono utilizzate principalmente chiamate asincrone. Ciò consente al cliente di lavorare in parallelo con richieste diverse. È possibile utilizzare l'approccio sincrono, ma è meno produttivo.

Le due operazioni di cui abbiamo parlato sono update/write, che modificano i dati. Questi sono crea, setData, sincronizza, elimina. E leggi esiste, getData, getChildren.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Ora alcuni esempi di come creare primitive per lavorare in un sistema distribuito. Ad esempio, relativo alla configurazione di qualcosa. È apparso un nuovo lavoratore. Abbiamo aggiunto la macchina e avviato il processo. E ci sono le seguenti tre domande. Come interroga ZooKeeper per la configurazione? E se vogliamo cambiare la configurazione, come la modifichiamo? E dopo averlo cambiato, come lo ottengono i lavoratori che avevamo?

ZooKeeper lo rende relativamente semplice. Ad esempio, c'è il nostro albero znode. C'è un nodo per la nostra applicazione qui, creiamo un nodo aggiuntivo al suo interno, che contiene i dati della configurazione. Questi possono o meno essere parametri separati. Poiché la dimensione è piccola, anche la dimensione della configurazione è solitamente piccola, quindi è del tutto possibile memorizzarla qui.

Stai usando il metodo getData per ottenere la configurazione per il lavoratore dal nodo. Impostato su vero. Se per qualche motivo questo nodo non esiste, ne verremo informati quando apparirà o quando cambierà. Se vogliamo sapere che qualcosa è cambiato, lo impostiamo su true. E se i dati in questo nodo cambiano, lo sapremo.

ImpostaDati. Impostiamo i dati, impostiamo “-1”, cioè non controlliamo la versione, assumiamo di avere sempre una configurazione, non abbiamo bisogno di memorizzare molte configurazioni. Se hai bisogno di immagazzinare molto, dovrai aggiungere un altro livello. Qui crediamo che ce ne sia solo uno, quindi aggiorniamo solo quello più recente, quindi non controlliamo la versione. In questo momento, tutti i clienti che si sono abbonati in precedenza ricevono una notifica che qualcosa è cambiato in questo nodo. E dopo averli ricevuti, devono anche richiedere nuovamente i dati. La notifica è che non ricevono i dati stessi, ma solo la notifica delle modifiche. Successivamente devono richiedere nuovi dati.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

La seconda opzione per utilizzare la primitiva è appartenenza al gruppo. Abbiamo un'applicazione distribuita, ci sono molti lavoratori e vogliamo capire che sono tutti a posto. Pertanto, devono registrarsi per dimostrare di lavorare nella nostra applicazione. E vogliamo anche scoprire, dal processo Master o da qualche altra parte, tutti i lavoratori attivi che abbiamo attualmente.

Come facciamo questo? Per l'applicazione, creiamo un nodo di lavoro e vi aggiungiamo un sottolivello utilizzando il metodo create. Ho un errore sulla diapositiva. Qui hai bisogno sequenziale specificare, tutti i lavoratori verranno creati uno per uno. E l'applicazione, richiedendo tutti i dati sui figli di questo nodo, riceve tutti i lavoratori attivi esistenti.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Questa è un'implementazione così terribile di come ciò possa essere fatto nel codice Java. Partiamo dalla fine, con il metodo principale. Questa è la nostra classe, creiamo il suo metodo. Come primo argomento utilizziamo host, a cui ci connettiamo, ovvero lo impostiamo come argomento. E il secondo argomento è il nome del gruppo.

Come avviene la connessione? Questo è un semplice esempio dell'API utilizzata. Qui tutto è relativamente semplice. Esiste una classe standard ZooKeeper. Gli passiamo gli host. E imposta il timeout, ad esempio, su 5 secondi. E abbiamo un membro chiamato connectSignal. In sostanza, creiamo un gruppo lungo il percorso trasmesso. Non scriviamo dati lì, anche se qualcosa avrebbe potuto essere scritto. E il nodo qui è di tipo persistente. Essenzialmente, questo è un normale nodo regolare che esisterà sempre. Qui è dove viene creata la sessione. Questa è l'implementazione del client stesso. Il nostro cliente invierà messaggi periodici indicando che la sessione è attiva. E quando terminiamo la sessione, chiamiamo chiusura e basta, la sessione cade. Questo nel caso in cui qualcosa non funzioni, in modo che ZooKeeper lo scopra e interrompa la sessione.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Come bloccare una risorsa? Qui tutto è un po’ più complicato. Abbiamo una serie di lavoratori, c'è qualche risorsa che vogliamo bloccare. Per fare ciò, creiamo un nodo separato, ad esempio, chiamato lock1. Se siamo riusciti a crearlo, allora abbiamo un lucchetto qui. E se non siamo riusciti a crearlo, il lavoratore tenta di ottenere getData da qui e poiché il nodo è già stato creato, inseriamo qui un osservatore e nel momento in cui lo stato di questo nodo cambia, lo sapremo. E possiamo provare ad avere tempo per ricrearlo. Se abbiamo preso questo nodo, preso questo lock, dopo che non avremo più bisogno del lock, lo abbandoneremo, poiché il nodo esiste solo all'interno della sessione. Di conseguenza, scomparirà. E un altro cliente, nell'ambito di un'altra sessione, potrà prendere il blocco su questo nodo, o meglio, riceverà una notifica che qualcosa è cambiato e potrà provare a farlo in tempo.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Un altro esempio di come scegliere il leader principale. Questo è un po’ più complicato, ma anche relativamente semplice. Cosa sta succedendo qui? C'è un nodo principale che aggrega tutti i lavoratori. Stiamo cercando di ottenere dati sul leader. Se ciò è avvenuto con successo, ad es. abbiamo ricevuto alcuni dati, il nostro lavoratore inizia a seguire questo leader. Crede che esista già un leader.

Se il leader muore per qualche motivo, ad esempio, cade, proviamo a creare un nuovo leader. E se ci riusciamo, il nostro lavoratore diventa il leader. E se qualcuno in questo momento è riuscito a creare un nuovo leader, allora cerchiamo di capire chi è e poi seguirlo.

Qui nasce il cosiddetto effetto gregge, cioè l'effetto gregge, perché quando muore un leader, colui che sarà primo in tempo diventerà il leader.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Quando acquisisci una risorsa, puoi provare a utilizzare un approccio leggermente diverso, che è il seguente. Ad esempio, vogliamo ottenere un lucchetto, ma senza l'effetto hert. Consisterà nel fatto che la nostra applicazione richiede elenchi di tutti gli ID nodo per un nodo già esistente con un lucchetto. E se prima il nodo per il quale abbiamo creato un blocco è il più piccolo del set che abbiamo ricevuto, significa che abbiamo catturato il blocco. Controlliamo di aver ricevuto un lucchetto. Come controllo, ci sarà una condizione che l'ID che abbiamo ricevuto durante la creazione di un nuovo blocco sia minimo. E se lo abbiamo ricevuto, lavoriamo ulteriormente.

Se c'è un certo ID più piccolo del nostro lucchetto, mettiamo un osservatore su questo evento e aspettiamo la notifica finché qualcosa non cambia. Cioè, abbiamo ricevuto questo blocco. E finché non cadrà, non diventeremo l'ID minimo e non riceveremo il blocco minimo, e quindi potremo accedere. E se questa condizione non viene soddisfatta, andiamo immediatamente qui e proviamo a ottenere di nuovo questo lucchetto, perché qualcosa potrebbe essere cambiato durante questo periodo.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

In cosa consiste ZooKeeper? Ci sono 4 cose principali. Si tratta di processi di elaborazione - Richiesta. E anche ZooKeeper Atomic Broadcast. È presente un registro di commit in cui vengono registrate tutte le operazioni. E lo stesso DB replicato in memoria, ovvero il database stesso in cui è archiviato l'intero albero.

Vale la pena notare che tutte le operazioni di scrittura passano attraverso il Request Processor. E le operazioni di lettura vanno direttamente al database in memoria.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Il database stesso è completamente replicato. Tutte le istanze di ZooKeeper memorizzano una copia completa dei dati.

Per ripristinare il database dopo un arresto anomalo, è disponibile un registro di commit. La pratica standard prevede che prima che i dati entrino in memoria, vengano scritti lì in modo che, in caso di arresto anomalo, questo registro possa essere riprodotto e lo stato del sistema possa essere ripristinato. Vengono inoltre utilizzate istantanee periodiche del database.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

ZooKeeper Atomic Broadcast è uno strumento utilizzato per mantenere i dati replicati.

ZAB seleziona internamente un leader dal punto di vista del nodo ZooKeeper. Altri nodi diventano suoi seguaci e si aspettano alcune azioni da lei. Se ricevono iscrizioni, le inoltrano tutte al leader. Prima esegue un'operazione di scrittura e poi invia un messaggio su cosa è cambiato ai suoi follower. Questa, infatti, deve essere eseguita in modo atomico, cioè l'operazione di registrazione e trasmissione dell'insieme deve essere eseguita in modo atomico, garantendo così la coerenza dei dati.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop" Elabora solo le richieste di scrittura. Il suo compito principale è trasformare l'operazione in un aggiornamento transazionale. Questa è una richiesta generata appositamente.

E qui vale la pena notare che è garantita l'idempotenza degli aggiornamenti per la stessa operazione. Cos'è? Questa cosa, se eseguita due volte, avrà lo stesso stato, ovvero la richiesta stessa non cambierà. E questo deve essere fatto in modo che, in caso di arresto anomalo, sia possibile riavviare l'operazione, ripristinando così le modifiche che al momento sono cadute. In questo caso lo stato del sistema diventerà lo stesso, cioè non dovrebbe accadere che una serie degli stessi, ad esempio processi di aggiornamento, portino a stati finali del sistema diversi.

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

"Hadoop. ZooKeeper" dalla serie Technostream del gruppo Mail.Ru "Metodi per l'elaborazione distribuita di grandi volumi di dati in Hadoop"

Fonte: habr.com

Aggiungi un commento