Apache Zookeeper Tutorial für verteilte Anwendungen

Von Sean Mackrory, Cloudera Inc. Es ist allgemein anerkannt, dass Sie niemals Ihre eigenen kryptographischen Algorithmen entwerfen oder implementieren sollten,…

Von Sean Mackrory, Cloudera Inc.

Es ist allgemein anerkannt, dass Sie niemals Ihre eigenen kryptographischen Algorithmen entwerfen oder implementieren sollten, sondern stattdessen gut getestete, von Experten begutachtete Bibliotheken verwenden sollten. Das Gleiche gilt für verteilte Systeme: Wenn Sie eigene Protokolle für die Koordinierung eines Clusters entwickeln, wird dies mit ziemlicher Sicherheit zu Frustration und Misserfolg führen.

Die Architektur eines verteilten Systems ist kein triviales Problem. Es ist sehr anfällig für Race Conditions, Deadlocks und Inkonsistenzen. Die Koordination von Clustern schnell und skalierbar zu machen, ist ebenso schwierig wie ihre Zuverlässigkeit. Hier kommt Apache ZooKeeper ins Spiel, ein Koordinationsdienst, der Ihnen die Werkzeuge an die Hand gibt, die Sie zum Schreiben korrekter verteilter Anwendungen benötigen.

Mit ZooKeeper werden diese schwierigen Probleme einmalig gelöst, so dass Sie Ihre Anwendung erstellen können, ohne das Rad neu erfinden zu müssen. ZooKeeper wird bereits von Apache HBase, HDFS und anderen Apache Hadoop-Projekten verwendet, um hochverfügbare Dienste bereitzustellen und ganz allgemein die verteilte Programmierung zu erleichtern. In diesem Blogbeitrag erfahren Sie, wie Sie ZooKeeper verwenden können, um wichtige Funktionen in Ihrer verteilten Software einfach und sicher zu implementieren.

So funktioniert ZooKeeper

ZooKeeper läuft auf einem Cluster von Servern, einem so genannten Ensemble, die den Zustand Ihrer Daten gemeinsam nutzen. (Dabei kann es sich um dieselben Rechner handeln, auf denen auch andere Hadoop-Dienste laufen, oder um einen separaten Cluster). Jede Änderung gilt erst dann als erfolgreich, wenn sie auf ein Quorum (mindestens die Hälfte) der Server im Ensemble geschrieben wurde. Innerhalb des Ensembles wird ein Anführer gewählt. Wenn zwei sich widersprechende Änderungen gleichzeitig vorgenommen werden, ist diejenige erfolgreich, die vom Anführer zuerst verarbeitet wird, und die andere schlägt fehl. ZooKeeper garantiert, dass Schreibvorgänge von ein und demselben Client in der Reihenfolge verarbeitet werden, in der sie von diesem Client gesendet wurden. Diese Garantie und andere unten beschriebene Funktionen ermöglichen die Implementierung von Sperren, Warteschlangen und anderen wichtigen Primitiven für verteilte Warteschlangen. Das Ergebnis eines Schreibvorgangs gibt einem Knoten die Gewissheit, dass ein identischer Schreibvorgang bei einem anderen Knoten nicht erfolgreich war.

Eine Folge der Funktionsweise von ZooKeeper ist, dass ein Server alle Client-Sitzungen trennt, wenn er länger als eine konfigurierbare Zeitspanne keine Verbindung zum Quorum herstellen konnte. Der Server hat keine Möglichkeit festzustellen, ob die anderen Server tatsächlich ausgefallen sind oder ob er nur aufgrund einer Netzwerkpartition von ihnen getrennt wurde, und kann daher die Konsistenz mit dem Rest des Ensembles nicht mehr garantieren. Solange mehr als die Hälfte des Ensembles in Betrieb ist, kann der Cluster trotz des Ausfalls einzelner Server weiterarbeiten. Wenn ein ausgefallener Server wieder online ist, wird er mit dem Rest des Ensembles synchronisiert und kann seinen Dienst wieder aufnehmen.

Am besten betreiben Sie Ihr ZooKeeper-Ensemble mit einer ungeraden Anzahl von Servern; typische Ensemblegrößen sind drei, fünf oder sieben. Wenn Sie z.B. fünf Server betreiben und drei ausfallen, ist der Cluster nicht verfügbar (Sie können also einen Server zur Wartung ausfallen lassen und trotzdem einen unerwarteten Ausfall überstehen). Wenn Sie jedoch sechs Server betreiben, ist der Cluster auch nach drei Ausfällen noch nicht verfügbar, aber die Wahrscheinlichkeit von drei gleichzeitigen Ausfällen ist nun etwas höher. Denken Sie auch daran, dass Sie, wenn Sie mehr Server hinzufügen, zwar mehr Ausfälle tolerieren können, aber auch einen geringeren Schreibdurchsatz haben werden. ( In der Apache-Dokumentation finden Sie eine schöne Illustration der Leistungsmerkmale verschiedener ZooKeeper-Ensemblegrößen).

Installation von ZooKeeper

Sie müssen Java installiert haben, bevor Sie ZooKeeper ausführen können (Client-Bindungen sind in verschiedenen anderen Sprachen verfügbar). Cloudera empfiehlt derzeit Oracle Java 6 für den produktiven Einsatz, aber diese Beispiele sollten auch mit OpenJDK 6 / 7 problemlos funktionieren. Anschließend müssen Sie das richtige CDH4-Paket-Repository für Ihr System installieren und das Paket zookeeper (erforderlich für jeden Rechner, der sich mit ZooKeeper verbindet) und das Paket zookeeper-server (erforderlich für jeden Rechner im ZooKeeper-Ensemble) installieren. Schauen Sie sich die Anweisungen für Ihr spezifisches System an, um die richtige URL und die richtigen Befehle zu erhalten, aber die Installation auf einem Ubuntu-System wird etwa so aussehen:

$ wget http://archive.cloudera.com/.../cdh4-repository_1.0_all.deb
$ sudo dpkg -i cdh4-repository_1.0_all.deb
$ sudo apt-get update
$ sudo apt-get install zookeeper zookeeper-server
...
JMX enabled by default
Using config: /etc/zookeeper/conf/zoo.cfg
ZooKeeper data directory is missing at /var/lib/zookeeper fix the path or run initialize
invoke-rc.d: initscript zookeeper-server, action "start" failed.

Die Warnungen, die Sie sehen, weisen darauf hin, dass ZooKeeper bei der ersten Ausführung auf einem bestimmten Host etwas Speicherplatz initialisieren muss. Sie können dies wie unten gezeigt tun und einen ZooKeeper-Server starten, der in einer Einzelknoten-/Standalone-Konfiguration läuft.

$ sudo service zookeeper-server init
No myid provided, be sure to specify it in /var/lib/zookeeper/myid if using non-standalone
$ sudo service zookeeper-server start
JMX enabled by default
Using config: /etc/zookeeper/conf/zoo.cfg
Starting zookeeper ... STARTED

Die ZooKeeper CLI

ZooKeeper wird mit einem Befehlszeilen-Client für die interaktive Nutzung geliefert, obwohl Sie in der Praxis eine der Programmiersprachenbindungen direkt aus Ihrer Anwendung heraus verwenden würden. Wir werden hier nur die grundlegenden Prinzipien der Verwendung von ZooKeeper mit dem Befehlszeilen-Client demonstrieren.

Starten Sie den Client, indem Sie den Befehl zookeeper-client ausführen. Die anfängliche Eingabeaufforderung kann durch einige Protokollmeldungen verdeckt sein, klicken Sie also einfach auf , wenn Sie sie nicht sehen. Geben Sie ls / oder help ein, um die anderen möglichen Befehle zu sehen.

$ zookeeper-client
  ...
  [zk: localhost:2181(CONNECTED) 0] ls /
  [zookeeper]
  [zk: localhost:2181(CONNECTED) 1] help

Dies ist vergleichbar mit der Shell und dem Dateisystem von UNIX-ähnlichen Systemen. ZooKeeper speichert seine Daten in einer Hierarchie von znodes. Jeder znode kann Daten enthalten (wie eine Datei) und Kinder haben (wie ein Verzeichnis). ZooKeeper ist dafür gedacht, mit kleinen Datenmengen in jedem znode zu arbeiten: Die Standardgrenze liegt bei 1 MB.

Lesen und Schreiben von Daten

Das Erstellen eines znode ist so einfach wie die Angabe des Pfades und des Inhalts. Erstellen Sie einen leeren znode, der als übergeordnetes ‚Verzeichnis‘ dient, und einen anderen znode als dessen Kind:

[zk: localhost:2181(CONNECTED) 2] create /zk-demo ''
Created /zk-demo
[zk: localhost:2181(CONNECTED) 3] create /zk-demo/my-node 'Hello!'
Created /zk-demo/my-node

Sie können dann den Inhalt dieser znodes mit dem Befehl get lesen. Die in dem znode enthaltenen Daten werden in der ersten Zeile gedruckt und danach werden die Metadaten aufgelistet (die meisten Metadaten wurden in diesen Beispielen der Kürze halber durch den Text ersetzt).

[zk: localhost:2181(CONNECTED) 4] get /zk-demo/my-node
'Hello!'
<metadata>
dataVersion = 0
<metadata>

Sie können znodes natürlich auch nach der Erstellung ändern. Beachten Sie, dass die dataVersion-Werte geändert wurden (ebenso wie der geänderte Zeitstempel – andere Metadaten wurden der Kürze halber weggelassen).

[zk: localhost:2181(CONNECTED) 5] set /zk-demo/my-node 'Goodbye!'
<metadata>
dataVersion = 1
<metadata>
[zk: localhost:2181(CONNECTED) 6] get /zk-demo/my-node
'Goodbye!'
<metadata>
dataVersion = 1
<metadata>

Sie können auch znodes löschen. znodes, die Kinder haben, können nicht gelöscht werden (es sei denn, ihre Kinder werden zuerst gelöscht). Es gibt einen rmr-Befehl, der dies für Sie erledigt.

[zk: localhost:2181(CONNECTED) 7] delete /zk-demo/my-node 
[zk: localhost:2181(CONNECTED) 8] ls /zk-demo
[]

Sequentielle und ephemere znodes

Neben dem Standardtyp znode gibt es zwei spezielle Typen von znode: sequentiell und ephemer. Sie können diese erstellen, indem Sie die Flags -s und -e an den Befehl create übergeben. (Sie können auch beide Typen auf einen znode anwenden.) Sequentielle Knoten werden mit einem numerischen Suffix erstellt, das an den angegebenen Namen angehängt wird, und ZooKeeper garantiert, dass zwei gleichzeitig erstellte Knoten nicht die gleiche Nummer erhalten.

[zk: localhost:2181(CONNECTED) 9] create -s /zk-demo/sequential one
Created /zk-demo/sequential0000000002
[zk: localhost:2181(CONNECTED) 10] create -s /zk-demo/sequential two
Created /zk-demo/sequential0000000003
[zk: localhost:2181(CONNECTED) 11] ls /zk-demo
[sequential0000000003, sequential0000000002]
[zk: localhost:2181(CONNECTED) 12] get /zk-demo/sequential0000000002 one
one
<metadata>

Beachten Sie, dass die Nummerierung auf den vorherigen Kindern basiert, die denselben Elternteil hatten – der erste sequenzielle Knoten, den wir erstellt haben, war also tatsächlich Nummer 2. Diese Funktion ermöglicht es Ihnen, verteilte Mutexe zu erstellen. Wenn ein Client den Mutex halten möchte, erstellt er einen sequenziellen Knoten. Wenn er dann der znode mit der niedrigsten Nummer mit diesem Namen ist, hält er die Sperre. Wenn nicht, wartet er. Um den Mutex freizugeben, löscht er den Knoten, so dass der nächste znode die Sperre halten kann.

Sie können ein sehr einfaches Master-Wahlsystem implementieren, indem Sie sequenzielle znodes ephemer machen. Ephemere Knoten werden automatisch gelöscht, wenn der Client, der sie erstellt hat, die Verbindung trennt (was bedeutet, dass ZooKeeper Ihnen auch bei der Fehlererkennung helfen kann – ein weiteres schwieriges Problem in verteilten Systemen). Clients können sich absichtlich abmelden, wenn sie heruntergefahren werden, oder sie können vom Cluster als abgemeldet betrachtet werden, weil der Client den konfigurierten Timeout überschritten hat, ohne einen Heartbeat zu senden. Der Knoten, der den niedrigsten sequenziellen ephemeren Knoten erstellt hat, übernimmt die Rolle des „Masters“. Wenn der Rechner abstürzt oder die JVM zu lange für die Garbage Collection pausiert, wird der ephemere Knoten gelöscht und der nächste in Frage kommende Knoten kann seinen Platz einnehmen.

[zk: localhost:2181(CONNECTED) 13] create -e -s /zk-demo/ephemeral data
Created /zk-demo/ephemeral
[zk: localhost:2181(CONNECTED) 14] ls /zk-demo
[sequential0000000003, sequential0000000002, ephemeral0000000003]
[zk: localhost:2181(CONNECTED) 15] quit
Quitting...
$ zookeeper-client
Connecting to localhost:2181
Welcome to ZooKeeper!
[zk: localhost:2181(CONNECTED) 0] ls /zk-demo
[sequential0000000003, sequential0000000002]

Uhren

ZooKeeper kann Sie auch über Änderungen am Inhalt eines znode oder an den Kindern eines znode informieren. Um einen „Watch“ für die Daten eines Znode zu registrieren, müssen Sie mit den Befehlen get oder stat auf den aktuellen Inhalt oder die Metadaten zugreifen und einen zusätzlichen Parameter übergeben, der den Watch anfordert. Um die Kinder eines znode zu beobachten, übergeben Sie denselben Parameter, wenn Sie die Kinder mit ls abrufen.

[zk: localhost:2181(CONNECTED) 1] create /zk-demo/watch-this data
Created /watch-this
[zk: localhost:2181(CONNECTED) 2] get /zk-demo/watch-this true
data
<metadata>

Ändern Sie dieselbe znode (entweder vom aktuellen ZooKeeper-Client oder von einem anderen), und Sie werden die folgende Meldung im Terminal sehen:

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/watch-this

Beachten Sie, dass Uhren nur einmal ausgelöst werden. Wenn Sie in Zukunft über Änderungen benachrichtigt werden möchten, müssen Sie die Watch jedes Mal zurücksetzen, wenn sie ausgelöst wird. Mit Watches können Sie ZooKeeper verwenden, um asynchrone, ereignisbasierte Systeme zu implementieren und Knoten zu benachrichtigen, wenn ihre lokalen Kopien der Daten in ZooKeeper veraltet sind.

Versionierung und ACLs

Wenn Sie sich die Metadaten ansehen, die in den vorherigen Befehlen aufgeführt sind, werden Sie Elemente sehen, die in vielen Dateisystemen üblich sind und Funktionen, die oben besprochen wurden: Erstellungszeitpunkt, Änderungszeitpunkt (und entsprechende Transaktions-IDs), die Größe des Inhalts in Bytes und den Ersteller des Knotens (falls ephemer). Sie werden auch einige Metadaten für Funktionen sehen, die dazu beitragen, die Integrität und Sicherheit der Daten zu gewährleisten: Datenversionierung und ACLs. Zum Beispiel:

cZxid = 0x00
ctime = Sun Jan 00 00:00:00 UTC 2013
mZxid = 0x00
mtime = Sun Jan 00 00:00:00 UTC 2013
pZxid = 0x00
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 0

Die aktuelle Version der Daten wird jedes Mal angegeben, wenn Sie sie lesen oder schreiben. Sie kann auch als Teil eines Schreibbefehls angegeben werden (ein Test-und-Satz-Vorgang). Wenn ein Schreibversuch mit einer veralteten Version durchgeführt wird, schlägt er fehl. Dies ist nützlich, um sicherzustellen, dass Sie keine Änderungen überschreiben, die Ihr Client noch nicht verarbeitet hat.

ZooKeeper unterstützt auch die Verwendung von Zugriffskontrolllisten (Access Control Lists, ACLs) und verschiedene Authentifizierungssysteme. Mit ACLs können Sie fein abgestufte Berechtigungen festlegen, um zu definieren, welche Benutzer und Gruppen die einzelnen znode erstellen, lesen, aktualisieren oder löschen dürfen. Die Verwendung von ACLs in ZooKeeper würde den Rahmen dieses Artikels sprengen, aber Sie können auf der Website des Projekts mehr darüber lesen.

Ideen für die Verwendung von ZooKeeper

Alle oben beschriebenen Mechanismen sind über verschiedene Programmiersprachenanbindungen zugänglich, so dass Sie ZooKeeper nutzen können, um bessere verteilte Anwendungen zu schreiben. Mehrere Hadoop-Projekte verwenden ZooKeeper bereits zur Koordinierung des Clusters und zur Bereitstellung hochverfügbarer verteilter Dienste. Am bekanntesten ist vielleicht Apache HBase, das ZooKeeper verwendet, um den Master, die Regionalserver und den Status der im Cluster verteilten Daten zu verfolgen.

Hier finden Sie einige weitere Beispiele, wie ZooKeeper für Sie nützlich sein könnte. Details zu den Algorithmen, die für viele dieser Anwendungsfälle erforderlich sind, finden Sie hier.

    • Gruppenzugehörigkeit und NamensdiensteIndemSie jeden Knoten einen ephemeren znode für sich selbst (und alle Rollen, die er möglicherweise erfüllt) registrieren lassen, können Sie ZooKeeper als Ersatz für DNS innerhalb Ihres Clusters verwenden. Knoten, die ausfallen, werden automatisch aus der Liste entfernt, und Ihr Cluster verfügt stets über ein aktuelles Verzeichnis der aktiven Knoten.
    • Verteilte Mutexe und MasterwahlWirhaben diese potenziellen Einsatzmöglichkeiten von ZooKeeper oben im Zusammenhang mit sequenziellen Knoten besprochen. Diese Funktionen können Ihnen helfen, ein automatisches Failover innerhalb Ihres Clusters zu implementieren, den gleichzeitigen Zugriff auf Ressourcen zu koordinieren und andere Entscheidungen in Ihrem Cluster sicher zu treffen.
    • Asynchrone Nachrichtenübermittlung und Event-BroadcastingAuch wennandere Tools besser für die Nachrichtenübermittlung geeignet sind, wenn der Durchsatz im Vordergrund steht, habe ich festgestellt, dass ZooKeeper bei Bedarf recht nützlich für den Aufbau eines einfachen Pub/Sub-Systems ist. In einem Fall benötigte ein Cluster eine lange Abfolge von Aktionen, die in den Stunden nach dem Hinzufügen oder Entfernen eines Knotens im Cluster ausgeführt werden sollten. Bei Bedarf wurde die Abfolge von Aktionen in ZooKeeper als eine Gruppe von aufeinanderfolgenden Knoten geladen, die eine Warteschlange bildeten. Der „Master“-Knoten verarbeitete jede Aktion zum vorgesehenen Zeitpunkt und in der richtigen Reihenfolge. Der Prozess dauerte mehrere Stunden und es bestand die Möglichkeit, dass der Master-Knoten in dieser Zeit abstürzt oder außer Betrieb genommen wird. Da ZooKeeper den Fortschritt jeder Aktion aufzeichnete, konnte ein anderer Knoten im Falle eines Problems dort weitermachen, wo der Master aufgehört hatte.
    • Zentralisierte KonfigurationsverwaltungDie Verwendung vonZooKeeper zur Speicherung Ihrer Konfigurationsinformationen hat zwei wesentliche Vorteile. Erstens muss neuen Knoten nur mitgeteilt werden, wie sie sich mit ZooKeeper verbinden können. Anschließend können sie alle anderen Konfigurationsinformationen herunterladen und selbst bestimmen, welche Rolle sie im Cluster spielen sollen. Zweitens kann Ihre Anwendung Änderungen an der Konfiguration abonnieren, so dass Sie die Konfiguration über einen ZooKeeper-Client optimieren und das Verhalten des Clusters zur Laufzeit ändern können.

Einpacken

Wenn sie falsch gemacht wird, kann verteilte Software am schwierigsten zu debuggen sein. Richtig gemacht, können Sie jedoch mehr Daten verarbeiten, und zwar zuverlässiger und in kürzerer Zeit. Mit Apache ZooKeeper können Sie den Zustand Ihrer Daten sicher einschätzen und Ihren Cluster richtig koordinieren. Sie haben gesehen, wie einfach es ist, einen ZooKeeper-Server einzurichten und zum Laufen zu bringen. (Wenn Sie ein CDH-Benutzer sind, haben Sie vielleicht sogar schon ein Ensemble laufen!) Denken Sie darüber nach, wie ZooKeeper Ihnen dabei helfen kann, robustere Systeme aufzubauen, und werfen Sie einen Blick in die CDH-Dokumentation und auf die Apache-Projektwebsite, um weitere Informationen über den Betrieb dieser Pakete in einer Produktionsumgebung zu erhalten.

You Might Also Like

Vom Suchunternehmen zum praktischen KI-Pionier: Unsere Vision für 2025 und darüber hinaus

CEO Mike Sinoway gibt Einblicke in die Zukunft der KI und stellt...

Read More

Wenn KI schief geht: Fehlschläge in der realen Welt und wie man sie vermeidet

Lassen Sie nicht zu, dass Ihr KI-Chatbot einen 50.000 Dollar teuren Tahoe...

Read More

Lucidworks Kernpakete: Branchenoptimierte KI-Such- und Personalisierungslösungen

Entdecken Sie unsere umfassenden Core Packages, die Analytics Studio, Commerce Studio und...

Read More

Quick Links