Hadoop Distributed File System


Dieser Artikel bezieht sich auf die aktuelle stable-Version 1.0.3.

Inhalt

Beschreibung
Architektur
Staging
Quellen
Siehe auch


Beschreibung

Das Hadoop Distributed File System (HDFS) ist ein verteiltes Dateisystem, welches neben MapReduce eine der zwei Kernkomponenten von Hadoop bildet und ursprünglich für Apache Nutch entwickelt wurde. HDFS zeichnet sich durch seine hohe Ausfallsicherheit aus und wurde für den Betrieb auf kostengünstiger Hardware entwickelt. Eine schnelle Fehlererkennung und Wiederherstellung von Daten ist ein Basisziel von HDFS. Dabei wurde beim Design von der Annahme ausgegangen, dass Hardwareausfall nicht die Ausnahme, sondern die Regel ist.
Ein weiteres Ziel ist die Verwaltung von enormen Datenbeständen (Petabyte-Bereich). Dabei liegt dem Design zugrunde, dass eine übliche Dateigröße im HDFS im Gigabyte- bis Terabyte-Bereich liegt. Insofern wurde speziell auf die Bedürfnisse großer Dateien eingegangen. Davon ist auch die Interaktion mit dem Dateisystem betroffen. HDFS zielt mehr auf Stapelverarbeitung, anstelle von einer interaktiven Nutzung mit dem Anwendern ab. Aus dem Grund gibt HDFS hohen Datendurchsatzraten den Vorzug vor niedrigen Zugriffszeiten. Des weiteren setzt HDFS auf ein write-once-read-many-Modell und bietet sich somit als perfekte Ergänzung zum MapReduce-Konzept oder Webcrawlern an.


Architektur

Grafik der HDFS-Architektur
HDFS-Architektur im Überblick
Quelle: hadoop.apache.org, "Hadoop 1.0.3 Documentation", 08.05.2012
http://hadoop.apache.org/common/docs/r1.0.3/hdfs_design.html

HDFS setzt auf eine Master-/Slave-Architektur. Ein HDFS-Cluster besteht aus einem Master, dem Namenode und mehreren Slaves, den Datanodes. Dabei ist der Master für die Verwaltung des Namespace im HDFS verantwortlich und reguliert den Zugriff auf die gespeicherten Daten durch die Clients. Zudem führt er Operationen, wie das Öffnen, Schließen und Umbenennen von Dateien aus und bestimmt die Verteilung von Datenblöcken im Cluster. Der Namenode ist so konzipiert, dass durch ihn niemals Nutzdaten fließen. Die Slaves speichern Blöcke von Daten und sind verantwortlich für die Abarbeitung von Schreib- und Leseoperationen. Auf Anweisung des Masters erstellen, replizieren und löschen sie Datenblöcke.
Dateien werden in Datenblöcke gesplittet und im Cluster verteilt. Die Blockgröße ist konfigurierbar und gilt für alle Dateien im Cluster. Im Sinne der Ausfallsicherheit und erhöhten Zugriffskapazitäten werden Kopien der Blöcke angefertigt und im Cluster verteilt. Der Replikationsfaktor beschreibt die Anzahl von Kopien pro Block und kann für jede Datei separat konfiguriert werden, auch nachträglich. So ist es bspw. möglich die Anzahl von Zugriffen auf gefragte Dateien zu erhöhen.

Dabei sind der Namenode und die Datanodes als "Software" zu verstehen. HDFS wurde in Java realisiert, was jede Maschine, die in der Lage ist, Java auszuführen, auch dazu befähigt selbst als Name- oder Datanode zu fungieren.

Der Namensraum (Namespace)

In HDFS wurden die typischen Funktionalitäten eines Dateisystems integriert. Es können Dateien und Ordner erstellt und gelöscht, verschoben und umbenannt werden. Diese unterliegen einer hierarchischen Ordnung, wie sie auch aus anderen Dateisystemen bekannt ist. Der Namensraum speichert also den Pfad von Dateien und Ordnern im HDFS. Der Pfad zu dem Unterordner bar, des Ordners foo, der direkt unter der Wurzel liegt, wäre somit: /foo/bar.
Soft- oder Hardlinks auf Ordner oder Dateien können im HDFS nicht erstellt werden!

Rechteverwaltung

Jede Datei und jeder Ordner im HDFS ist mit einem Benutzer und einer Gruppe verknüpft. Das Rechtemodell orientiert sich dabei am POSIX-Modell. Mit dem, z.B. aus UNIX bekannten, chmod-Kommando lassen sich Attribute für das Lesen (r), Schreiben (w) und "Ausführen" (x) setzen ("Ausführen" meint hier bspw. das Auflisten von Ordnerinhalten). Dabei bewegt sich der Benutzer stets unter dem Nutzernamen, den er auch auf dem Hostsystems inne hat.
Hat sich der Benutzer bspw. als User auf dem Host-System authentifiziert, würde er sich auch als Nutzer User im HDFS bewegen. Neu erstellte Dateien und Ordner würden dem Besitzer User zugesprochen werden. Der Nachteil, der sich daraus ergibt, ist offensichtlich. Hat der Benutzer die Möglichkeit, seinen Nutzernamen zu ändern (bspw. durch das Verwenden eines eigenen PCs/Laptops), könnte er sich die Berechtigungen eines jeden Nutzers im HDFS aneignen.

Metadaten

Der Namenode führt ein Transaktionslog, den "EditLog", um Änderungen an den Metadaten des Namensraum zu registrieren. Legt ein Client bspw. eine neue Datei im HDFS an, protokolliert der Namenode Metadaten für diese Datei. Dazu gehört u.a. der Dateiname, der Replikationsfaktor, die Speicherorte der einzelnen Blöcke usw. Der EditLog wird nicht im HDFS gespeichert, sondern auf dem lokalen Dateisystem des Hosts, auf dem der Namenode betrieben wird. Selbiges gilt auch für den Namensraum der in einer einzigen Datei ("FsImage") gespeichert wird. Eine Abbild dieser Datei liegt immer als Kopie im RAM des Hosts. Dabei wurde darauf geachtet, die Metadaten-Größe so gering wie möglich zu halten, um auch bei wenig Arbeitsspeicher möglichst viele Dateien und Verzeichnisse verwalten zu können.
Beim Hochfahren des Namenodes werden alle Änderungen aus dem EditLog im in-memory-Abbild der FsImage-Datei übernommen und diese im Anschluss in einer aktuellen FsImage-Datei gesichert. Der EditLog kann nach dieser Aktion überschrieben werden, da alle wichtigen Informationen in der FsImage-Datei gesichert wurden.
Fällt der Namenode aus, bricht das ganze HDFS zusammen. FsImage und EditLog bilden die zentrale Struktur des HDFS ab. Der Namenode kann konfiguriert werden, mehrere Kopien von den beiden Dateien zu verwalten, welche in regelmäßigen Abständen synchronisiert werden. Dies kann in einer Reduktion der Namensraum-Transaktionen pro Sekunde resultieren, was aber von untergeordneter Relevanz ist, da HDFS-Anwendungen i.d.R. Daten-intensiv und nicht Metadaten-intensiv sind. Eine automatische Erkennung eines Namenode-Ausfalls und -Wechsels auf einen anderen Namenode wird aktuell nicht unterstützt.

Kommunikation

Die gesamte Kommunikation wurde über die Protokolle TCP und IP realisiert. Darauf setzen ein ClientProtocol und ein DatanodeProtocol auf. Über eine RPC-Abstraktion auf dem Namenode werden beide Protokolle verpackt und verarbeitet. Antworten erfolgen über den Rückgabewert des RPC-Aufrufs. Der Namenode selbst initiiert keine Verbindung zu den Datanodes oder Clients.

Neben der Kommunikation des Clients mit dem Namenode ist der Blockreport von besonderer Bedeutung. Dieser wird beim Hochfahren und in periodischen Abständen von den Datanodes generiert und an den Namenode versandt. Der Blockreport umfasst eine Auflistung aller HDFS-Datenblöcke, die auf dem Datanode gespeichert sind. Neben den Blockreports erfolgt das periodische Senden von Heartbeats. Diese signalisieren dem Namenode die Funktionstüchtigkeit des Datanodes.

Re-Replikation und Datenintegrität

Bleibt der Empfang von Heartbeats für einen Datanode aus, wird er vom Namenode als "tot" gekennzeichnet und keine Schreib- oder Leseoperationen mehr an ihn delegiert. Durch den Ausfalls eines Datanodes kann der Replikationsfaktor, also die Anzahl von Kopien pro Datenblock, unterschritten werden. In diesem Fall wird vom Namenode ein neuer Datanode bestimmt, auf den eine Kopie von einem anderen Datanode übertragen wird. Datenblöcke werden als "sicher" eingestuft, wenn ausreichend Kopien, entsprechend dem Replikationsfaktor, vorhanden sind.

Die Datenintegrität wird über Prüfsummen gewährleistet. Die Client-Anwendung im HDFS generieren eine Prüfsumme für jeden neu erstellten Datenblock (siehe Staging), welche in einer separaten, versteckten Datei auf dem HDFS abgelegt werden. Empfängt der Client Daten, deren berechnete Prüfsumme nicht mit der hinterlegten übereinstimmen, kann er die Daten wahlweise erneut anfordern oder verwerfen.

FS Shell

Die Interaktion mit dem Dateisystem erfolgt in erster Linie über die Kommandozeile. Dabei werden die gängigen Befehle für das Anlegen und Auflisten von Verzeichnissen etc. unterstützt. Bsp.:

  • Das Anlegen eines neuen Verzeichnisses "foo" im Wurzelverzeichnis "/" erfolgt über den Befehl:
    • hadoop dfs -mkdir /foo
  • Der Inhalt des Verzeichnisses wird durch diesen Befehl aufgelistet:
    • hadoop dfs -ls /foo

Über die Shell können aber auch administrative Befehle abgesendet werden.

  • Dieser Befehl bspw. generiert eine Liste aller aktiven Datanodes:
    • hadoop dfsadmin -report

Eine umfangreiche Liste alle Befehle kann der Referenz von Hadoop entnommen werden.


Staging

Eine Client-Anfrage, eine neue Datei im HDFS zu erstellen, wird nicht direkt an den Namenode weitergeleitet. Die Daten werden zunächst lokal, auf dem Dateisystems des Clients abgelegt. Erst wenn die eingestellte Blockgröße (standardmäßig 64MB, für den produktiven Einsatz werden 128MB empfohlen) erreicht ist, wird der Namenode kontaktiert. Der Namenode trägt die Datei ins HDFS ein und weist ihm einen Datenblock zu. Im Anschluss wird der Client über den Zieldatenblock und den Datanode informiert, der ihn aufnehmen soll. Die Client kann somit beginnen, den Datenblock auf dem Node mit den Daten aus der lokalen Datei zu befüllen. Wird eine Datei geschlossen, werden die verbleibenden Daten in einem kleineren Datenblock auf einen zugewiesenen Datanode abgelegt. Dies gilt auch für Dateien, deren Größe die eingestellte Blockgröße nicht erreichen. Würde der Namenode während des Anlegens einer Datei ausfallen, würden die Daten verloren gehen.

Replication Pipelining

Replication Pipelining
Replication Pipelining (Bei Replikationsfaktor: 3)

Wie schon unter dem Punkt Staging beschrieben, wird dem Client der Ziel-Datanode zugewiesen, auf welchen er seine Daten übertragen soll. Daten werden dabei in 4KB-Blöcken versendet. Der empfangende Datanode legt den 4KB-Block ab und sendet ihn an einen weiteren Datanode, sofern der Replikationsfaktor mehr Kopien vorschreibt. Dieser Datanode wird ebenfalls wieder vom Namenode bestimmt.
Wird für eine Datei bspw. ein Replikationsfaktor von 3 vorgeschrieben, so würde der Client Daten an den ersten Datanode senden, der wiederum an den zweiten und dieser wiederum an den dritten.
Bei der Verteilung von Kopien findet die infrastrukturelle Position der Datanodes im Cluster Beachtung. Hierbei sei anzumerken, dass HDFS eine Unterteilung von Clustern in Racks vorsieht, welche wiederum aus mehreren Nodes bestehen. Bezogen auf das Beispiel mit dem Replikationsfaktor 3, würde versucht werden, die erste Kopie im lokalen Rack abzulegen, die zweite in einem entfernten Rack und die dritte in dem selben entfernten Rack, aber auf einem anderen Datanode. Unter der Prämisse, dass der Datendurchsatz von Datanodes innerhalb des Racks größer ist, wie zwischen verschiedenen Racks, wird durch dieses Vorgehensmodell die Netzwerkauslastung auf das Nötigste reduziert. Es wird ebenfalls davon ausgegangen, dass der Ausfall eines gesamten Racks wesentlich unwahrscheinlicher ist, wie der Ausfall eines einzelnen Knotens.


Quellen

  • Borthakur, Dhruba, Hadoop 1.0.3 Documentation, 08.05.2012, http://hadoop.apache.org/common/docs/r1.0.3/hdfs_design.html
  • Wartala, Ramon, Hadoop Zuverlässige, verteilte und skalierbare Big-Data-Anwendungen, Open Source Press 2012
  • White, Tom, Hadoop The Defintive Guide, O'Reilly Media Inc. 3. Auflage, May 2012

Siehe auch:


Kategorie: Datenbanken, NoSQL, Hadoop, H