Wie funktioniert Hadoop-Prozess zeichnet split across block boundaries?
Entsprechend der Hadoop - The Definitive Guide
Den logischen Datensätze, die FileInputFormats definieren in der Regel nicht ordentlich passen in die HDFS-Blöcke. Zum Beispiel, ein TextInputFormat der logischen Datensätze sind Linien, auf denen die cross-HDFS-Grenzen mehr als oft nicht. Dies hat keinen Einfluss auf die Funktionalität des Programm—Zeilen sind nicht zu kurz oder defekt ist, zum Beispiel—aber es lohnt sich zu wissen, darüber, wie es bedeutet, dass die Daten-lokale Karten - (Karten, die laufen auf dem gleichen host wie Ihre input-Daten) führen einige remote liest. Die geringen overhead verursacht, ist in der Regel nicht signifikant.
Angenommen, ein Datensatz ist aufgeteilt in zwei Blöcke (b1 und b2). Der mapper die Verarbeitung des ersten Blocks (b1) feststellen, dass die Letzte Zeile nicht mit einem EOL-separator und holt sich den Rest von der Zeile aus dem nächsten block von Daten (b2).
Wie funktioniert der mapper der Bearbeitung des zweiten Blocks (b2) bestimmen, dass der erste Datensatz ist unvollständig und soll-Prozess ab dem zweiten Datensatz in dem block (b2)?
InformationsquelleAutor Praveen Sripati | 2013-01-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Interessante Frage, ich verbrachte einige Zeit auf der Suche nach dem code für die details und hier sind meine Gedanken. Die splits sind vom Kunden bearbeitet von
InputFormat.getSplits
, so dass Sie einen Blick auf FileInputFormat gibt folgende info:max(minSize, min(maxSize, blockSize))
womaxSize
entsprichtmapred.max.split.size
undminSize
istmapred.min.split.size
.Teilen Sie die Datei in verschiedene
FileSplit
s, basierend auf dem split-Größe, die oben berechnet. Was hier wichtig ist, dass jederFileSplit
wird initialisiert mit einerstart
parameter entsprechend der offset in der input-Datei. Es gibt noch keine Behandlung, die Linien an diesem Punkt. Der relevante Teil des Codes sieht wie folgt aus:Danach, wenn man sich die
LineRecordReader
die definiert ist durch dieTextInputFormat
ist, wo die Linien behandelt werden:LineRecordReader
es zu instanziieren versucht eineLineReader
was ist eine Abstraktion, die in der Lage sein zu Lesen Zeilen überFSDataInputStream
. Es gibt 2 Fälle:CompressionCodec
definiert, dann wird dieser codec ist verantwortlich für den Umgang mit Grenzen. Wahrscheinlich nicht relevant für Ihre Frage.Wenn es keine codec allerdings, das ist, wo die Dinge sind interessant: wenn die
start
IhrerInputSplit
ist anders als 0, dann werden Sie backtrack 1 Zeichen und dann das überspringen der ersten Zeile, der Sie begegnen, gekennzeichnet durch \n oder \r\n (Windows) ! Der backtrack ist wichtig, weil im Falle Ihrer Linie Grenzen sind die gleichen wie split-Grenzen, dies gewährleistet, dass Sie nicht überspringen Sie die gültigen Zeile. Hier ist der relevante code:So, da die Teilungen entsprechen den Clients, die Mapper müssen nicht nacheinander ablaufen, jeder mapper weiß schon, wenn er neds zu verwerfen, die erste Zeile ist oder nicht.
Also im Grunde, wenn Sie haben 2 Zeilen mit jeweils 100 MB in der gleichen Datei, und zur Vereinfachung nehmen wir an, der split size ist 64 MB. Dann, wenn die input-splits berechnet werden, haben wir das folgende Szenario:
LineReader.readLine
Funktion, ich glaube nicht, dass es relevant ist, um Ihre Frage, aber können Sie mehr details hinzufügen, wenn nötig.Nehmen wir an es gibt zwei Linien mit genauen 64MB in der Eingabe-und so die InputSplits passiert genau bei der Zeile Grenzen. So, der mapper immer ignorieren die Linie, im zweiten block starten, weil != 0.
In diesem Fall ist der zweite mapper werden sehen, beginnen Sie != 0, so backtrack 1 Zeichen, das bringt Sie zurück, nur vor dem \n in der ersten Zeile und dann das überspringen von bis zu folgenden \n". So wird es überspringen der ersten Zeile, aber der Prozess in der zweiten Zeile als erwartet.
ist es möglich, dass die erste Zeile der Datei wird übersprungen, irgendwie? Konkret, ich habe die erste Zeile mit key=1, und Wert a, dann gibt es zwei weitere Linien mit dem gleichen Schlüssel irgendwo in der Datei, key=1, val=b und die Taste=1, val=c. Die Sache ist die, meine reducer erhält {1, [b,c]} und {1, [a]} anstelle von {1, [a,b,c]}. Dies geschieht nicht, wenn ich hinzufügen neue Zeile an den Anfang meiner Datei. Was könnte der Grund sein, Sir?
Was ist, wenn die Datei in HDFS ist ein Binär - Datei (im Gegensatz zu text-Datei, in der
\r\n, \n
stellt Rekord abschneiden)?InformationsquelleAutor Charles Menguy
Karte Reduzieren Algorithmus funktioniert nicht auf physischen Blöcke der Datei. Es funktioniert auf der logischen input-splits. Input-split hängt davon ab, wo der Datensatz geschrieben wurde. Ein Datensatz kann über zwei Mapper.
Den Weg HDFS eingerichtet wurde, bricht es, sehr große Dateien in großen Blöcken (Z. B. mess-128MB), und speichert drei Kopien von diesen Blöcken, die auf verschiedenen Knoten im cluster.
HDFS hat kein Bewusstsein für die Inhalte dieser Dateien. Eine Aufzeichnung kann gestartet wurden in Block-ein, aber am Ende ist der Datensatz vorhanden sein können, Block-b.
Um dieses problem zu lösen, Hadoop verwendet eine logische Darstellung der Daten in einer Datei gespeicherte Blöcke, bekannt als Eingang teilt. Wenn Sie einen MapReduce-Auftrag-client berechnet die input splits, es zahlen, wo die erste ganze Platte, ein block beginnt und wo Sie den letzten Datensatz im block endet.
Der entscheidende Punkt :
In Fällen, In denen Sie den letzten Datensatz in einem block ist unvollständig, die input-split enthält Informationen für den nächsten block und den byte-offset der Daten, die zur vollständigen Datensatz.
Haben Sie einen Blick auf unten Diagramm.
Haben Sie einen Blick auf diese Artikel und Verwandte SE Frage : Über Hadoop/HDFS-Datei-splitting
Können Sie mehr Lesen von Dokumentation
Den Map-reduce-framework stützt sich auf das InputFormat der job:
InputSplit[] getSplits(JobConf job,int numSplits
) ist die API kümmern sich um diese Dinge.FileInputFormat, die sich
InputFormat
umgesetztgetSplits
() - Methode. Haben Sie einen Blick auf die Interna dieser Methode auf grepcodeInformationsquelleAutor Ravindra babu
Sehe ich es wie folgt: InputFormat verantwortlich ist, zum aufteilen der Daten in logische spaltet unter Berücksichtigung der Art der Daten.
Nicht daran gehindert, es zu tun, obwohl es kann zu einem erheblichen Latenz zu den job - all die Logik und Lesen Sie die gewünschte split-Größe Grenzen passieren, in den jobtracker.
Einfachste Aufzeichnung bewusst-input-format TextInputFormat. Es funktioniert wie folgt (so weit wie ich verstanden habe aus dem code) - Eingabe-format erstellen, spaltet sich nach der Größe, unabhängig von den Linien, aber LineRecordReader immer :
a) Überspringen der ersten Zeile in der split (oder einen Teil davon), wenn es nicht der erste split
b) Lesen einer Zeile nach der Grenze der split am Ende (wenn die Daten verfügbar, so ist es nicht der Letzte split).
Skip first line in the split (or part of it), if it is not the first split
- wenn der erste Datensatz in nicht-ersten block abgeschlossen ist, dann ist nicht sicher, wie diese Logik funktioniert.Soweit ich sehe, der code - jedes geteilte gelesen, was hat es + nächste Zeile. Also, wenn Zeilenumbruch ist nicht auf den block boundary - es ist ok. Wie genau behandelt den Fall, wenn der Zeilenumbruch wird exakt an den block gebunden verstanden werden - ich lese ein bisschen mehr code
InformationsquelleAutor David Gruzman
Von dem, was ich verstanden hab, wenn die
FileSplit
initialisiert wird für den ersten block, der default-Konstruktor aufgerufen wird. Deshalb werden die Werte für start und Länge gleich null sind, zunächst. Durch das Ende der Verarbeitung des Faust-block, der, wenn die Letzte Zeile unvollständig ist, dann wird der Wert der Länge wird größer sein als die Länge der split, und Lesen Sie die erste Zeile des nächsten block, wie gut. Aufgrund dieser dem Wert der start für den ersten block größer sein wird als null, und unter dieser Bedingung, dieLineRecordReader
überspringen die erste Zeile des zweiten Blocks. (Siehe Quelle)Im Falle der letzten Zeile des ersten Blocks abgeschlossen ist, dann wird der Wert der Länge ist gleich der Länge des ersten Blocks und der Wert der start für den zweiten block wird gleich null sein. In diesem Fall wird die
LineRecordReader
wird nicht überspringen der ersten Zeile und Lesen Sie den zweiten block bilden den Anfang.Sinn macht?
InformationsquelleAutor aa8y
Vom hadoop-source-code von LineRecordReader.java Konstruktor: ich finde einige Kommentare :
von diesem ich glaube, hadoop Lesen wird eine zusätzliche Zeile für jede Teilung(am Ende der aktuellen split, Lesen die nächste Zeile in die nächste split), und wenn nicht die erste Trennung, die erste Zeile wegwerfen. so, dass keine Linie Datensatz verloren und unvollständig
InformationsquelleAutor Shenghai.Geng
Den Mapper nicht haben, um zu kommunizieren. Die Datei-Blöcke im HDFS und können die aktuellen mapper(RecordReader) Lesen kann der block, dass der restliche Teil der Strecke. Dies geschieht hinter den kulissen.
InformationsquelleAutor user3507308