Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Ich schlage vor, das Transkript der Vorlesung „Hadoop. ZooKeeper“ aus der Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“ zu lesen.

Was ist ZooKeeper und sein Platz im Hadoop-Ökosystem? Die Lüge über verteiltes Rechnen. Schema eines standardmäßigen verteilten Systems. Schwierigkeiten bei der Koordinierung verteilter Systeme. Typische Koordinationsprobleme. Die Prinzipien hinter dem Design von ZooKeeper. ZooKeeper-Datenmodell. Znode-Flags. Sitzungen. Client-API. Primitive (Konfiguration, Gruppenmitgliedschaft, einfache Sperren, Anführerwahl, Sperren ohne Herdeneffekt). ZooKeeper-Architektur. ZooKeeper-DB. ZAB. Anforderungshandler.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Heute werden wir über ZooKeeper sprechen. Dieses Ding ist sehr nützlich. Es verfügt wie jedes Apache Hadoop-Produkt über ein Logo. Es zeigt eine Person.

Davor haben wir vor allem darüber gesprochen, wie Daten dort verarbeitet werden können, wie man sie speichert, also wie man sie irgendwie nutzt und irgendwie damit arbeitet. Und heute möchte ich ein wenig über die Erstellung verteilter Anwendungen sprechen. Und ZooKeeper ist eines dieser Dinge, die es einfach machen. Hierbei handelt es sich um eine Art Dienst, der für eine Art Koordinierung des Zusammenspiels von Prozessen in verteilten Systemen, in verteilten Anwendungen konzipiert ist.

Der Bedarf an solchen Anwendungen wird von Tag zu Tag größer, darum geht es in unserem Kurs. Einerseits können Sie mit MapReduce und diesem vorgefertigten Framework diese Komplexität nivellieren und den Programmierer davon befreien, Grundelemente wie Interaktion und Koordination von Prozessen zu schreiben. Aber andererseits gibt es keine Garantie dafür, dass dies sowieso nicht nötig sein wird. Nicht immer ersetzen MapReduce oder andere vorgefertigte Frameworks einige Fälle vollständig, die in diesem Fall nicht implementiert werden können. Einschließlich MapReduce selbst und einer Reihe anderer Apache-Projekte handelt es sich tatsächlich ebenfalls um verteilte Anwendungen. Und um das Schreiben zu erleichtern, haben sie ZooKeeper geschrieben.

Wie alle Hadoop-bezogenen Anwendungen wurde es von Yahoo! entwickelt. Jetzt ist es auch die offizielle Anwendung von Apache. Es wird nicht so aktiv entwickelt wie HBase. Wenn Sie zu JIRA HBase gehen, gibt es jeden Tag viele Aufgaben für Fehler, viele Vorschläge zur Optimierung, das heißt, das Leben im Projekt geht ständig weiter. Und ZooKeeper ist einerseits ein relativ einfaches Produkt, andererseits gewährleistet dies seine Zuverlässigkeit. Und es ist ziemlich einfach zu verwenden, weshalb es zum Standard in Anwendungen innerhalb des Hadoop-Ökosystems geworden ist. Daher hielt ich es für sinnvoll, es noch einmal durchzulesen, um zu verstehen, wie es funktioniert und wie man es verwendet.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Dies ist ein Bild aus einem unserer Vorträge. Wir können sagen, dass es orthogonal zu allem ist, was wir bisher betrachtet haben. Und alles, was hier angegeben ist, funktioniert bis zu einem gewissen Grad mit ZooKeeper, das heißt, es ist ein Dienst, der alle diese Produkte nutzt. Weder HDFS noch MapReduce schreiben eigene ähnliche Dienste, die speziell für sie funktionieren würden. Dementsprechend kommt ZooKeeper zum Einsatz. Und es vereinfacht die Entwicklung und einige Dinge im Zusammenhang mit Fehlern.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Woher kommt das alles? Es scheint, als hätten sie zwei Anwendungen parallel auf verschiedenen Computern gestartet, sie mit einem Kabel oder in einem Netz verbunden, und alles funktionierte. Das Problem besteht jedoch darin, dass das Netzwerk unzuverlässig ist. Wenn Sie den Datenverkehr überwachen oder auf niedriger Ebene beobachten, was dort passiert und wie Clients im Netzwerk interagieren, können Sie häufig feststellen, dass einige Pakete verloren gehen und erneut gesendet werden. Nicht umsonst wurden TCP-Protokolle entwickelt, mit denen Sie eine bestimmte Sitzung aufbauen und die Zustellung von Nachrichten garantieren können. Aber auf jeden Fall kann auch TCP nicht immer sparen. Alles hat eine Auszeit. Möglicherweise fällt das Netzwerk für eine Weile aus. Sie kann einfach blinzeln. Und das alles führt dazu, dass man sich nicht darauf verlassen kann, dass das Netzwerk zuverlässig ist. Dies ist der Hauptunterschied zum Schreiben paralleler Anwendungen, die auf einem Computer oder einem Supercomputer ausgeführt werden, wo es kein Netzwerk gibt, wo es einen zuverlässigeren Datenaustauschbus im Speicher gibt. Und das ist der grundlegende Unterschied.

Unter anderem kommt es bei der Nutzung des Netzwerks immer zu einer gewissen Latenz. Die Festplatte hat es auch, aber das Web hat mehr. Latenz ist eine Art Verzögerungszeit, die sowohl klein als auch sehr bedeutend sein kann.

Die Netzwerktopologie verändert sich. Was Topologie ist, ist die Platzierung unserer Netzwerkausrüstung. Es gibt Rechenzentren, es gibt Racks, die da stehen, es gibt Kerzen. All dies kann neu verbunden, verschoben usw. werden. All dies muss ebenfalls berücksichtigt werden. IPs ändern sich, das Routing ändert sich, über das wir Datenverkehr haben. Dies muss ebenfalls berücksichtigt werden.

Auch hinsichtlich der Ausstattung kann sich das Netzwerk ändern. Aus der Praxis kann ich sagen, dass unsere Netzwerkingenieure sehr gerne regelmäßig etwas an den Kerzen aktualisieren. Plötzlich gibt es eine neue Firmware und sie sind nicht besonders an einem Hadoop-Cluster interessiert. Sie haben ihre eigene Arbeit. Für sie geht es vor allem darum, dass das Netzwerk funktioniert. Dementsprechend möchten sie dort etwas erneut hochladen, um ein Flashen auf ihrer Hardware durchzuführen, während sich die Hardware auch periodisch ändert. All dies muss in irgendeiner Weise berücksichtigt werden. All dies betrifft unsere verteilte Anwendung.

Normalerweise glauben Menschen, die aus irgendeinem Grund mit der Arbeit mit großen Datenmengen beginnen, dass das Web grenzenlos ist. Wenn eine Datei mehrere Terabyte groß ist, können Sie sie auf Ihren Server oder Computer übertragen und mit öffnen Katze und schau. Ein weiterer Fehler ist Vim Protokolle ansehen. Tun Sie das niemals, denn es ist schlecht. Denn Vim versucht, alles zu puffern, alles in den Speicher zu laden, insbesondere wenn wir anfangen, durch dieses Protokoll zu navigieren und nach etwas zu suchen. Das sind Dinge, die vergessen werden, aber eine Überlegung wert sind.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Es ist einfacher, ein Programm zu schreiben, das auf einem Computer mit einem Prozessor läuft.

Wenn unser System wächst, wollen wir das alles parallelisieren, und zwar nicht nur auf einem Computer, sondern auch auf einem Cluster. Es stellt sich die Frage: Wie kann man dieses Geschäft koordinieren? Unsere Anwendungen interagieren möglicherweise nicht einmal miteinander, aber wir haben mehrere Prozesse parallel auf mehreren Servern gestartet. Und wie kann man überwachen, dass bei ihnen alles gut läuft? Sie verschicken zum Beispiel etwas über das Web. Sie müssen irgendwo über ihren Zustand schreiben, zum Beispiel in eine Datenbank oder in ein Protokoll, dieses Protokoll dann aggregieren und es dann irgendwo analysieren. Außerdem müssen Sie berücksichtigen, dass der Prozess funktioniert hat, funktioniert hat, plötzlich ein Fehler darin aufgetreten ist oder er abgestürzt ist. Wie schnell werden wir dann davon erfahren?

Es ist klar, dass dies alles schnell überwacht werden kann. Das ist auch gut, aber die Überwachung ist eine begrenzte Sache, die es Ihnen ermöglicht, einige Dinge auf höchster Ebene zu überwachen.

Wenn wir möchten, dass unsere Prozesse miteinander interagieren, beispielsweise Daten aneinander senden, stellt sich auch die Frage: Wie wird dies geschehen? Wird es eine Art Race Condition geben, werden sie sich gegenseitig überschreiben, werden die Daten korrekt ankommen, geht unterwegs etwas verloren? Es ist notwendig, eine Art Protokoll usw. zu entwickeln.

Die Koordination all dieser Prozesse ist keine triviale Sache. Und es zwingt den Entwickler, noch tiefer zu gehen und Systeme entweder von Grund auf oder nicht ganz von Grund auf zu schreiben, aber so einfach ist das nicht.

Wenn Sie einen kryptografischen Algorithmus entwickelt oder sogar implementiert haben, dann nehmen Sie ihn und werfen Sie ihn sofort weg, denn höchstwahrscheinlich wird er bei Ihnen nicht funktionieren. Es wird höchstwahrscheinlich eine Reihe von Fehlern enthalten, die Sie vergessen haben, vorherzusehen. Verwenden Sie es auf keinen Fall für etwas Ernstes, da es höchstwahrscheinlich instabil sein wird. Denn alle Algorithmen, die es gibt, werden über einen sehr langen Zeitraum getestet. Es wird von der Community nach Fehlern durchsucht. Dies ist ein separates Problem. Und hier ist es genauso. Wenn es möglich ist, eine Art Prozesssynchronisation nicht selbst zu implementieren, dann ist es besser, dies nicht zu tun, da es ziemlich schwierig ist und Sie auf den unsicheren Weg führt, ständig nach Fehlern zu suchen.

Heute sprechen wir über ZooKeeper. Einerseits handelt es sich um ein Framework, andererseits um einen Service, der dem Entwickler das Leben erleichtert und es so einfach wie möglich macht, die Logik umzusetzen und unsere Prozesse zu koordinieren.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Erinnern Sie sich, wie ein standardmäßiges verteiltes System aussehen könnte. Darüber haben wir gesprochen – das ist HDFS, HBase. Es gibt einen Master-Prozess, der Arbeiter verwaltet, und Slave-Prozesse. Er ist verantwortlich für die Koordinierung und Verteilung von Aufgaben, die Wiederinbetriebnahme von Arbeitskräften, die Einführung neuer Arbeitskräfte und den Lastausgleich.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Eine fortgeschrittenere Sache ist der Koordinierungsdienst, d. h. die Koordinierungsaufgabe selbst wird in einen separaten Prozess verschoben und parallel dazu eine Art Backup oder Standby des Masters ausgeführt, da der Master möglicherweise abstürzt. Und wenn der Meister fällt, wird unser System nicht funktionieren. Wir führen ein Backup durch. Einige geben an, dass der Master zur Sicherung repliziert werden muss. Dies kann auch dem Koordinierungsdienst übertragen werden. Aber in diesem Schema koordiniert der Master selbst die Arbeiter, hier koordiniert der Dienst die Datenreplikation.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Eine fortgeschrittenere Option besteht darin, dass unser Service die gesamte Koordination übernimmt, wie es normalerweise der Fall ist. Er übernimmt die Verantwortung dafür, dass alles funktioniert. Und wenn etwas nicht funktioniert, finden wir es heraus und versuchen, diese Situation zu umgehen. In jedem Fall bleibt uns der Master, der irgendwie mit den Slaves interagiert und über einen bestimmten Dienst Daten, Informationen, Nachrichten usw. senden kann.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Es gibt ein noch fortgeschritteneres Schema: Wenn wir keinen Master haben, sind alle Knoten Master-Slaves, die sich in ihrem Verhalten unterscheiden. Trotzdem müssen sie miteinander interagieren, daher gibt es immer noch einen bestimmten Dienst zur Koordinierung dieser Aktionen. Wahrscheinlich passt Cassandra, die nach diesem Prinzip arbeitet, in dieses Schema.

Es ist schwer zu sagen, welches dieser Schemata am besten funktioniert. Jedes hat seine Vor- und Nachteile.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Und vor manchen Dingen muss man beim Meister keine Angst haben, denn wie die Praxis zeigt, neigt er nicht so sehr dazu, ständig zu geben. Hier geht es vor allem darum, die richtige Lösung für das Hosten dieses Dienstes auf einem separaten leistungsstarken Knoten zu wählen, damit dieser über genügend Ressourcen verfügt, damit Benutzer dort nach Möglichkeit keinen Zugriff haben, damit sie diesen Prozess nicht versehentlich abbrechen. Aber gleichzeitig ist es in einem solchen Schema viel einfacher, Arbeiter aus dem Master-Prozess zu verwalten, d. h. dieses Schema ist einfacher in der Umsetzung.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Und dieses Schema (oben) ist wahrscheinlich komplizierter, aber zuverlässiger.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Das Hauptproblem sind Teilausfälle. Wenn wir beispielsweise eine Nachricht über das Netzwerk senden, kommt es zu einem Unfall, und der Absender der Nachricht weiß nicht, ob seine Nachricht angekommen ist und was auf der Empfängerseite passiert ist, er weiß nicht, ob die Nachricht korrekt verarbeitet wurde , d.h. er erhält keine Bestätigung.

Dementsprechend müssen wir diese Situation verarbeiten. Und am einfachsten ist es, diese Nachricht erneut zu senden und zu warten, bis wir eine Antwort erhalten. In diesem Fall wird nirgendwo berücksichtigt, ob sich der Zustand des Empfängers geändert hat. Vielleicht senden wir eine Nachricht und fügen die gleichen Daten zweimal hinzu.

ZooKeeper bietet Möglichkeiten, mit solchen Ausfällen umzugehen, was auch uns das Leben erleichtert.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Wie bereits erwähnt, ähnelt dies dem Schreiben von Multithread-Programmen, der Hauptunterschied besteht jedoch darin, dass bei verteilten Anwendungen, die wir auf verschiedenen Maschinen erstellen, die einzige Möglichkeit zur Interaktion das Netzwerk ist. Im Wesentlichen handelt es sich hierbei um eine Shared-Nothing-Architektur. Jeder Prozess oder Dienst, der auf einer Maschine läuft, verfügt über einen eigenen Speicher, eine eigene Festplatte, einen eigenen Prozessor, den er mit niemandem teilt.

Wenn wir ein Multithread-Programm auf einem Computer schreiben, können wir den gemeinsam genutzten Speicher zum Datenaustausch verwenden. Wir haben dort einen Kontextwechsel, Prozesse können wechseln. Dies wirkt sich auf die Leistung aus. Einerseits gibt es so etwas im Programm auf dem Cluster nicht, aber es gibt Probleme mit dem Netzwerk.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Dementsprechend sind die Hauptprobleme, die beim Schreiben verteilter Systeme auftreten, die Konfiguration. Wir schreiben eine Bewerbung. Wenn es einfach ist, dann codieren wir alle möglichen Zahlen fest im Code, aber das ist unpraktisch, denn wenn wir entscheiden, dass wir statt einer halben Sekunde ein Timeout von einer Sekunde wollen, müssen wir die Anwendung neu kompilieren , rollen Sie alles noch einmal aus. Es ist eine Sache, wenn es sich auf einer Maschine befindet und man es einfach neu starten kann, und wenn wir viele Maschinen haben, müssen wir ständig alles kopieren. Wir müssen versuchen, die Anwendung konfigurierbar zu machen.

Hier sprechen wir über die statische Konfiguration für Systemprozesse. Dies ist möglicherweise nicht ganz der Fall, aus Sicht des Betriebssystems kann es sich um eine statische Konfiguration für unsere Prozesse handeln, d. h. es handelt sich um eine Konfiguration, die nicht einfach übernommen und aktualisiert werden kann.

Und es gibt auch eine dynamische Konfiguration. Dies sind die Parameter, die wir im laufenden Betrieb ändern möchten, damit sie dort übernommen werden.

Was ist hier das Problem? Wir haben die Konfiguration aktualisiert, ausgerollt, na und? Das Problem kann sein, dass wir einerseits die Konfiguration ausgerollt haben, aber das Neue vergessen haben, die Konfiguration blieb dort. Zweitens wurde während des Rollouts irgendwo die Konfiguration aktualisiert, irgendwo aber nicht. Und einige Prozesse unserer Anwendung, die auf demselben Computer ausgeführt werden, wurden mit einer neuen Konfiguration und irgendwo mit der alten neu gestartet. Dies kann dazu führen, dass unsere verteilte Anwendung hinsichtlich der Konfiguration nicht in einem konsistenten Zustand ist. Dieses Problem ist häufig. Für die dynamische Konfiguration ist dies relevanter, da davon ausgegangen wird, dass sie im laufenden Betrieb geändert werden kann.

Ein weiteres Problem ist die Gruppenmitgliedschaft. Wir haben immer eine Gruppe von Arbeitern, wir wollen immer wissen, wer von ihnen lebt und wer tot ist. Wenn es einen Meister gibt, muss er verstehen, welche Arbeiter an Kunden weitergeleitet werden können, damit diese mit Berechnungen beginnen oder mit Daten arbeiten, und welche nicht. Es stellt sich ständig das Problem, dass man wissen muss, wer in unserem Cluster arbeitet.

Ein weiteres typisches Problem ist die Wahl von Führungskräften, wenn wir wissen wollen, wer das Sagen hat. Ein Beispiel ist die Replikation, wenn wir über einen Prozess verfügen, der Schreibvorgänge akzeptiert und diese dann auf andere Prozesse repliziert. Er wird der Anführer sein, alle anderen werden ihm gehorchen und ihm folgen. Es ist notwendig, einen solchen Prozess zu wählen, der für alle eindeutig ist, damit es nicht dazu kommt, dass zwei Führungskräfte aussteigen.

Es gibt auch einen sich gegenseitig ausschließenden Zugriff. Hier ist das Problem komplexer. Es gibt so etwas wie einen Mutex, wenn Sie Multithread-Programme schreiben und möchten, dass der Zugriff auf eine Ressource, beispielsweise auf eine Speicherzelle, begrenzt und nur von einem Thread ausgeführt wird. Hier könnte die Ressource etwas abstrakter sein. Und verschiedene Anwendungen von verschiedenen Knoten unseres Netzwerks sollten nur exklusiven Zugriff auf diese Ressource erhalten und nicht, damit jeder sie ändern oder dort etwas schreiben kann. Das sind die sogenannten Schlösser.

Mit ZooKeeper können Sie alle diese Probleme bis zu einem gewissen Grad lösen. Und ich werde anhand von Beispielen zeigen, wie Ihnen das gelingt.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Es gibt keine blockierenden Grundelemente. Wenn wir anfangen, etwas zu verwenden, wartet dieses Grundelement nicht auf das Eintreten eines Ereignisses. Höchstwahrscheinlich wird dieses Ding asynchron funktionieren, sodass Prozesse nicht in dem Zustand hängen bleiben, in dem sie auf etwas warten. Das ist eine sehr nützliche Sache.

Alle Clientanfragen werden in der Reihenfolge der allgemeinen Warteschlange verarbeitet.

Und Kunden haben die Möglichkeit, Benachrichtigungen über Änderungen in einem bestimmten Zustand oder über Datenänderungen zu erhalten, bevor der Kunde die geänderten Daten selbst sieht.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

ZooKeeper kann in zwei Modi arbeiten. Der erste ist eigenständig, auf einem Knoten. Dies ist praktisch zum Testen. Und es kann auch im Cluster-Modus auf einer beliebigen Anzahl von Servern arbeiten. Wenn wir einen Cluster mit 100 Maschinen haben, ist es nicht notwendig, dass er auf 100 Maschinen funktioniert. Es reicht aus, einige Computer auszuwählen, auf denen Sie ZooKeeper ausführen können. Und es bekennt sich zum Prinzip der Hochverfügbarkeit. ZooKeeper behält eine vollständige Kopie der Daten auf jeder laufenden Instanz. Ich erzähle euch später, wie er das macht. Die Daten werden nicht geteilt und nicht partitioniert. Das ist einerseits ein Minus, dass wir nicht viel lagern können, andererseits ist das auch nicht nötig. Dafür ist es nicht konzipiert, es ist keine Datenbank.

Daten können clientseitig zwischengespeichert werden. Dies ist ein Standardprinzip, damit wir den Dienst nicht abrufen und nicht mit denselben Anforderungen laden. Ein kluger Kunde weiß das normalerweise und speichert es zu Hause.

Zum Beispiel hat sich etwas geändert. Es gibt einige Anwendungen. Wir haben einen neuen Leiter gewählt, der beispielsweise für die Verarbeitung von Schreibvorgängen verantwortlich ist. Und wir wollen die Daten replizieren. Eine Lösung besteht darin, einen Zyklus einzurichten. Und wir befragen ständig unseren Service – hat sich etwas geändert? Die zweite Option ist optimaler. Hierbei handelt es sich um einen Überwachungsmechanismus, der es Ihnen ermöglicht, Kunden darüber zu informieren, dass sich etwas geändert hat. Dies ist ressourcenschonender und bequemer für die Kunden.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Client ist der Benutzer, der ZooKeeper verwendet.

Server ist der ZooKeeper-Prozess selbst.

Znode ist die Kernfunktion von ZooKeeper. Alle Znodes werden von ZooKeeper im Speicher gespeichert und in einem hierarchischen Schema in Form eines Baums organisiert.

Es gibt zwei Arten von Operationen. Das erste ist Aktualisieren/Schreiben, wenn eine Operation den Status unseres Baums ändert. Der Baum ist allgemein.

Und es ist möglich, dass der Client eine Anfrage nicht erfüllt und unterbrochen wird, aber eine Sitzung aufbauen kann, mit der er mit ZooKeeper interagiert.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Das Datenmodell von ZooKeeper ähnelt einem Dateisystem. Es gibt ein Standard-Root, und dann sind wir durch die Verzeichnisse gegangen, die vom Root ausgehen. Und dann der Katalog der ersten Ebene, der zweiten Ebene. Es sind alles Znodes.

Jeder Knoten kann einige Daten speichern, die normalerweise nicht sehr groß sind, beispielsweise 10 Kilobyte. Und jeder Knoten kann eine bestimmte Anzahl von Kindern haben.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Znodes gibt es in verschiedenen Ausführungen. Sie können erstellt werden. Und wenn wir einen Znode erstellen, geben wir den Typ an, zu dem er gehören soll.

Es gibt zwei Arten. Die erste ist die vergängliche Flagge. Znode lebt innerhalb einer Sitzung. Beispielsweise hat der Client eine Sitzung aufgebaut. Und solange diese Sitzung am Leben ist, wird sie existieren. Dies ist notwendig, um nicht etwas Überflüssiges zu produzieren. Es eignet sich auch für solche Momente, in denen es für uns wichtig ist, Datenprimitive innerhalb der Sitzung zu speichern.

Der zweite Typ ist das sequentielle Flag. Es erhöht einen Zähler auf dem Weg zum Znode. Wir hatten zum Beispiel ein Verzeichnis mit der Anwendung 1_5. Und als wir den ersten Knoten erstellt haben, erhielt er p_1, der zweite - p_2. Und wenn wir diese Methode jedes Mal aufrufen, übergeben wir den vollständigen Pfad, der nur einen Teil des leeren Pfads angibt, und diese Zahl wird automatisch erhöht, da wir den Knotentyp angeben – sequentiell.

Regulärer Knoten. Sie wird ewig leben und den Namen tragen, den wir ihr sagen werden.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Eine weitere nützliche Sache ist die Uhrenflagge. Wenn wir es festlegen, kann der Client einige Ereignisse für einen bestimmten Knoten abonnieren. Wie das geht, werde ich später anhand eines Beispiels zeigen. ZooKeeper selbst benachrichtigt den Client, dass sich die Daten auf dem Knoten geändert haben. Gleichzeitig garantieren Benachrichtigungen nicht, dass neue Daten eingetroffen sind. Sie sagen nur, dass sich etwas geändert hat, sodass Sie die Daten später sowieso mit separaten Anrufen vergleichen müssen.

Und wie gesagt, die Datenreihenfolge wird durch Kilobyte bestimmt. Es besteht keine Notwendigkeit, dort große Textdaten zu speichern, da es sich hierbei nicht um eine Datenbank, sondern um einen Server zur Koordinierung von Aktionen handelt.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Ich erzähle Ihnen ein wenig über die Sitzungen. Wenn wir mehrere Server haben, können wir mithilfe der Sitzungs-ID transparent von Server zu Server wechseln. Es ist ziemlich praktisch.

Jede Sitzung hat eine Art Zeitüberschreitung. Eine Sitzung wird dadurch definiert, ob der Client während dieser Sitzung etwas an den Server sendet. Wenn er während des Timeouts nichts übermittelt hat, bricht die Sitzung ab oder der Client kann sie selbst schließen.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Es verfügt nicht über so viele Funktionen, aber Sie können mit dieser API alles Mögliche tun. Der Aufruf, den wir gesehen haben, erstellt einen Znode und benötigt drei Parameter. Dies ist der Pfad zum Znode und muss vom Stamm aus qualifiziert werden. Und auch das sind einige Daten, die wir dorthin übertragen wollen. Und die Art der Flagge. Und nach der Erstellung wird der Pfad an znode zurückgegeben.

Der zweite kann entfernt werden. Hier besteht der Clou darin, dass man als zweiten Parameter neben dem Pfad zu znode auch die Version angeben kann. Dementsprechend wird dieser Znode gelöscht, wenn seine Version, die wir übergeben haben, mit der tatsächlich vorhandenen Version übereinstimmt.

Wenn wir diese Version nicht prüfen möchten, übergeben wir einfach das Argument „-1“.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Drittens wird überprüft, ob Znode vorhanden ist. Gibt true zurück, wenn der Knoten existiert, andernfalls false.

Und dann erscheint Flag Watch, mit dem Sie die Überwachung für diesen Knoten einstellen können.

Sie können dieses Flag auch auf einem nicht vorhandenen Knoten setzen und erhalten eine Benachrichtigung, wenn es erscheint. Das ist auch nützlich.

Es folgen noch ein paar Anrufe Daten bekommen. Es ist klar, dass wir Daten per Znode abrufen können. Sie können auch die Flaggenüberwachung verwenden. In diesem Fall wird es nicht installiert, wenn kein Knoten vorhanden ist. Daher müssen Sie verstehen, dass es existiert, und dann die Daten abrufen.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Es gibt auch SetData. Hier übergeben wir die Version. Und wenn wir es weitergeben, werden die Daten auf dem Znode einer bestimmten Version aktualisiert.

Sie können auch „-1“ angeben, um diese Prüfung auszuschließen.

Eine weitere nützliche Methode ist getChildren. Wir können auch eine Liste aller dazugehörigen Znodes erhalten. Wir können dies beobachten, indem wir die Flag-Uhr setzen.

Und Methode synchronisieren ermöglicht das gleichzeitige Senden aller Änderungen und stellt so sicher, dass diese gespeichert werden und alle Daten vollständig geändert werden.

Wenn Sie Analogien zur konventionellen Programmierung ziehen, gibt es keine Garantie dafür, dass Sie Daten auf die Festplatte geschrieben haben, wenn Sie Methoden wie write verwenden, die etwas auf die Festplatte schreiben und nachdem diese eine Antwort an Sie zurückgegeben haben. Und selbst wenn das Betriebssystem sicher ist, dass alles geschrieben wurde, gibt es auf der Festplatte selbst Mechanismen, mit denen der Prozess die Pufferstufen durchläuft und erst danach die Daten auf der Festplatte abgelegt werden.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Meistens werden asynchrone Aufrufe verwendet. Dies ermöglicht es dem Client, verschiedene Anfragen parallel zu bearbeiten. Sie können den synchronen Ansatz verwenden, dieser ist jedoch weniger produktiv.

Die beiden Vorgänge, über die wir gesprochen haben, sind Aktualisierung/Schreiben, die die Daten ändern. Dies sind „Create“, „SetData“, „Sync“, „Delete“. Und lesen ist vorhanden, getData, getChildren.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Nun ein paar Beispiele, wie Sie Grundelemente in einem verteilten System zum Laufen bringen können. Zum Beispiel im Zusammenhang mit der Konfiguration von etwas. Ein neuer Arbeiter ist aufgetaucht. Wir haben ein Auto hinzugefügt und den Prozess gestartet. Und es gibt drei Fragen. Wie fordert es die Konfiguration von ZooKeeper an? Und wenn wir die Konfiguration ändern wollen, wie ändern wir sie dann? Und wie bekommen die Arbeiter, die wir hatten, es, nachdem wir es geändert haben?

In ZooKeeper ist dies relativ einfach möglich. Da ist zum Beispiel unser Baum-Znode. Hier gibt es einen Knoten für unsere Anwendung, wir erstellen darin einen zusätzlichen Knoten, der Daten aus der Konfiguration enthält. Dies können separate Parameter sein oder auch nicht. Da die Größe klein ist, ist die Größe der Konfiguration normalerweise auch klein, sodass es durchaus möglich ist, sie hier zu speichern.

Sie verwenden die Methode Daten bekommen um die Konfiguration für den Worker vom Knoten abzurufen. Auf true setzen. Sollte dieser Knoten aus irgendeinem Grund nicht existieren, werden wir darüber informiert, wenn er erscheint oder sich ändert. Wenn wir wissen wollen, dass sich etwas geändert hat, dann setzen wir es auf true. Und wenn sich die Daten in diesem Knoten ändern, werden wir davon erfahren.

SetData. Wir setzen die Daten, setzen „-1“, d.h. wir überprüfen die Version nicht, wir gehen davon aus, dass wir immer die gleiche Konfiguration haben, wir müssen nicht viele Konfigurationen speichern. Wenn Sie viel lagern müssen, müssen Sie eine weitere Ebene hinzufügen. Hier gehen wir davon aus, dass es sich um die einzige Version handelt, daher aktualisieren wir nur die neueste Version und überprüfen die Version nicht. In diesem Moment erhalten alle Kunden, die sich zuvor angemeldet haben, eine Benachrichtigung, dass sich in diesem Knoten etwas geändert hat. Und nachdem sie diese erhalten haben, müssen sie die Daten auch erneut anfordern. Die Benachrichtigung liegt darin, dass sie nicht die Daten selbst erhalten, sondern lediglich eine Benachrichtigung über Änderungen. Danach müssen sie neue Daten anfordern.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Die zweite Verwendung des Grundelements ist Gruppenmitgliedschaft. Wir haben eine verteilte Anwendung, wir haben eine Menge Worker und wir wollen verstehen, dass sie alle vorhanden sind. Daher müssen sie sich selbst registrieren, dass sie in unserer Anwendung arbeiten. Außerdem möchten wir mehr über alle aktiven Mitarbeiter erfahren, die wir derzeit haben, entweder aus dem Master-Prozess oder von woanders.

Wie machen wir es? Für die Anwendung erstellen wir einen Worker-Knoten und fügen dort mithilfe der Methode create eine Unterebene hinzu. Ich habe einen Fehler auf der Folie. Hier brauchen Sie sequenziell angeben, dann werden alle Worker einzeln erstellt. Und die Anwendung, die alle Daten über die untergeordneten Knoten dieses Knotens anfordert, erhält alle aktiven Arbeiter, die vorhanden sind.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hier ist eine so schreckliche Implementierung, wie dies in Java-Code durchgeführt werden kann. Beginnen wir am Ende mit der Hauptmethode. Das ist unsere Klasse, wir erstellen ihre Methode. Als erstes Argument verwenden wir host, wo wir uns verbinden, d.h. wir setzen es als Argument. Und als zweites Argument der Name der Gruppe.

Wie läuft die Verbindung? Dies ist ein einfaches Beispiel für die verwendete API. Hier ist alles relativ einfach. Es gibt eine Standard-ZooKeeper-Klasse. Wir geben ihm Gastgeber. Und legen Sie ein Timeout fest, zum Beispiel 5 Sekunden. Und wir haben ein Mitglied wie connectedSignal. Im Wesentlichen erstellen wir eine Gruppe anhand des übergebenen Pfads. Wir schreiben dort keine Daten, obwohl etwas geschrieben werden könnte. Und der Knoten hier ist vom Typ persistent. Tatsächlich ist dies ein gewöhnlicher regulärer Knoten, der ständig existiert. Hier wird die Sitzung erstellt. Dies ist die Implementierung des Clients selbst. Unser Kunde wird regelmäßig melden, dass die Sitzung aktiv ist. Und wenn wir die Sitzung abgeschlossen haben, rufen wir „Close“ auf und das war’s, die Sitzung wird abgebrochen. Dies geschieht für den Fall, dass bei uns etwas schiefgeht, sodass ZooKeeper davon erfährt und die Sitzung abbricht.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Wie sperre ich eine Ressource? Hier ist alles etwas komplizierter. Wir haben eine Reihe von Arbeitern, es gibt eine Art Ressource, die wir sperren möchten. Dazu erstellen wir einen separaten Knoten, beispielsweise mit dem Namen lock1. Wenn wir es schaffen konnten, dann haben wir hier eine Sperre bekommen. Und wenn wir es nicht erstellen konnten, dann versucht der Worker, GetData von hier abzurufen, und da der Knoten bereits erstellt wurde, platzieren wir hier einen Beobachter und in dem Moment, in dem sich der Status dieses Knotens ändert, werden wir davon erfahren Es. Und wir können versuchen, Zeit zu haben, es neu zu erschaffen. Wenn wir diesen Knoten genommen haben, haben wir diese Sperre genommen, und wenn wir die Sperre nicht mehr benötigen, werden wir sie ablehnen, da der Knoten nur innerhalb der Sitzung existiert. Dementsprechend wird es verschwinden. Und ein anderer Client innerhalb einer anderen Sitzung kann eine Sperre für diesen Knoten aufheben bzw. erhält eine Benachrichtigung, dass sich etwas geändert hat, und kann versuchen, dies rechtzeitig zu tun.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Ein weiteres Beispiel dafür, wie Sie den Hauptführer auswählen können. Das ist etwas komplizierter, aber auch relativ einfach. Was ist hier los? Es gibt einen Hauptknoten, der alle Arbeiter zusammenfasst. Wir versuchen, Daten über den Anführer zu bekommen. Wenn dies erfolgreich war, d. h. wir einige Daten erhalten haben, beginnt unser Mitarbeiter, diesem Anführer zu folgen. Er glaubt, dass der Anführer bereits da ist.

Wenn der Anführer aus irgendeinem Grund gestorben ist, zum Beispiel abgefallen ist, versuchen wir, einen neuen Anführer zu schaffen. Und wenn es uns gelingt, wird unser Mitarbeiter zum Anführer. Und wenn es jemandem in diesem Moment gelungen ist, einen neuen Anführer zu schaffen, dann versuchen wir zu verstehen, wer es ist, und ihm dann zu folgen.

Hier entsteht der sogenannte Herdeneffekt, also der Herdeneffekt, denn wenn der Anführer stirbt, wird derjenige zum Anführer, der als Erster rechtzeitig da ist.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Beim Erfassen einer Ressource können Sie versuchen, einen etwas anderen Ansatz zu verwenden, der wie folgt aussieht. Wir wollen zum Beispiel eine Sperre bekommen, aber ohne Hert-Effekt. Es besteht darin, dass unsere Anwendung Listen aller Knoten-IDs für einen bereits vorhandenen Knoten mit Sperre anfordert. Und wenn zuvor der Knoten, für den wir die Sperre erstellt haben, das Minimum des Satzes ist, den wir erhalten haben, bedeutet dies, dass wir die Sperre erfasst haben. Wir überprüfen, ob wir ein Schloss haben. Zur Kontrolle gibt es die Bedingung, dass die ID, die wir beim Erstellen einer neuen Sperre erhalten haben, die Mindest-ID ist. Und wenn wir es erhalten haben, dann arbeiten wir weiter.

Wenn es eine ID gibt, die kleiner als unsere Sperre ist, setzen wir einen Beobachter auf dieses Ereignis und warten auf eine Benachrichtigung, bis sich etwas ändert. Das heißt, wir haben dieses Schloss erhalten. Und bis es abfällt, werden wir nicht die Mindest-ID erreichen und wir werden nicht die Mindestsperre erhalten, und somit können wir sperren. Und wenn diese Bedingung nicht erfüllt ist, dann gehen wir sofort hierher und versuchen erneut, diese Sperre zu bekommen, denn in dieser Zeit könnte sich etwas geändert haben.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Woraus besteht ZooKeeper? Es gibt 4 Hauptdinge. Dies ist die Bearbeitung von Prozessen – Anfrage. Und auch ZooKeeper Atomic Broadcast. Es gibt ein Commit-Log, in dem alle Vorgänge aufgezeichnet werden. Und die In-Memory Replicated DB selbst, also die Datenbank selbst, in der dieser gesamte Baum gespeichert ist.

Es ist zu beachten, dass alle Schreibvorgänge über den Anforderungsprozessor erfolgen. Und Lesevorgänge gehen direkt an die In-Memory-Datenbank.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Die Datenbank selbst wird vollständig repliziert. Alle Instanzen von ZooKeeper speichern eine vollständige Kopie der Daten.

Um die Datenbank nach einem Absturz wiederherzustellen, gibt es ein Commit-Log. Es ist eine Standardpraxis, Daten dorthin zu schreiben, bevor sie in den Speicher gelangen, damit im Falle eines Absturzes dieses Protokoll wiedergegeben und der Zustand des Systems wiederhergestellt werden kann. Außerdem werden regelmäßige Datenbank-Snapshots angewendet.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

ZooKeeper Atomic Broadcast ist so etwas, das zur Verwaltung replizierter Daten verwendet wird.

ZAB wählt intern einen Anführer aus Sicht des ZooKeeper-Knotens. Andere Knoten werden zu ihren Anhängern und warten auf eine Aktion von ihr. Wenn bei ihnen Aufzeichnungen eintreffen, leiten sie diese alle an den Anführer weiter. Er führt den Schreibvorgang vor und sendet dann eine Nachricht darüber, was sich geändert hat, an seine Follower. Dies muss tatsächlich atomar erfolgen, d. h. der Aufzeichnungs- und Sendevorgang des Ganzen muss atomar erfolgen, um so die Datenkonsistenz zu gewährleisten.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“ Es verarbeitet nur Schreibanfragen. Seine Hauptaufgabe besteht darin, die Operation in eine transaktionale Aktualisierung umzuwandeln. Dies ist eine speziell ausgearbeitete Anfrage.

Und hier ist es erwähnenswert, dass die Idempotenz von Updates für denselben Vorgang garantiert ist. Was ist das? Wenn Sie dieses Ding zweimal ausführen, hat es denselben Status, d. h. die Anfrage selbst ändert sich nicht. Und Sie müssen dies tun, damit Sie im Falle eines Absturzes den Vorgang neu starten und so die aktuell ausgefallenen Änderungen übernehmen können. In diesem Fall wird der Zustand des Systems gleich, d. h. es sollte nicht so sein, dass eine Reihe gleicher, beispielsweise Aktualisierungsvorgänge, zu unterschiedlichen Endzuständen des Systems führen.

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Hadoop. ZooKeeper“ aus der Mail.Ru Group Technostrim-Reihe „Methoden zur verteilten Verarbeitung großer Datenmengen in Hadoop“

Source: habr.com

Kommentar hinzufügen