web-dev-qa-db-de.com

Spark Dataframe Write to CSV erstellt _temporary directory file im Standalone Cluster Mode

Ich führe spark job in einem Cluster mit 2 Arbeitsknoten aus! Ich verwende den folgenden Code (Spark Java) zum Speichern des berechneten Datenrahmens als CSV auf Arbeitsknoten.

dataframe.write().option("header","false").mode(SaveMode.Overwrite).csv(outputDirPath); Ich versuche zu verstehen, wie spark mehrere Teiledateien auf jeden Arbeitsknoten schreibt.

Run1) worker1 hat part files und SUCCESS; worker2 hat _temporarty/task*/part* Für jede Aufgabe werden die Teiledateien ausgeführt.

Run2) worker1 hat Teildateien und auch das Verzeichnis _temporary; worker2 hat multiple part files

Kann mir jemand helfen zu verstehen, warum dieses Verhalten ist? 1) Soll ich die Datensätze in outputDir/_temporary als Teil der Ausgabedatei zusammen mit dem part files in outputDir betrachten?

2) Soll das Verzeichnis _temporary nach der Ausführung des Jobs gelöscht werden und die Dateien part nach outputDir verschoben werden?

3) Warum können keine Teiledateien direkt unter dem Ausgabeverzeichnis erstellt werden?

coalesce(1) und repartition(1) können nicht ausgewählt werden, da sich die outputDir-Datei selbst um 500GB befindet.

Spark 2.0.2. 2.1.3 und Java 8, no HDFS

7

Nach der Analyse wurde festgestellt, dass mein Spark-Job fileoutputcommitter version 1 verwendet. Dies ist die Standardeinstellung. Dann habe ich config eingefügt, um fileoutputcommitter version 2 anstelle von version 1 zu verwenden, und in einem 10-Knoten-Spark-Standalone-Cluster in AWS getestet. Alle part-* files werden direkt unter der in der dataframe.write().option("header","false").mode(SaveMode.Overwrite).csv(outputDirPath) angegebenen outputDirPath generiert

Wir können die Eigenschaft festlegen

  1. Indem Sie dasselbe wie --conf 'spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version=2' in spark-submit command aufnehmen

  2. oder setzen Sie die Eigenschaft mit sparkContext javaSparkContext.hadoopConifiguration().set("mapreduce.fileoutputcommitter.algorithm.version","2")

Ich verstehe die Konsequenz im Falle von Fehlern wie in den spark docs beschrieben, aber ich habe das gewünschte Ergebnis erzielt!

spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version , defaultValue ist 1
Die Version des Committer-Algorithmus für die Dateiausgabe, gültige Algorithmus-Versionsnummer: 1 oder 2. Version 2 hat möglicherweise eine bessere Leistung, Version 1 kann jedoch in bestimmten Situationen besser mit Fehlern umgehen, wie in MAPREDUCE-4815 beschrieben.

0

TL; DR Um Daten mit dateisystembasierten Quellen ordnungsgemäß zu schreiben (oder zu lesen), benötigen Sie einen gemeinsam genutzten Speicher.

Das Verzeichnis _temporary ist Teil des grundlegenden Festschreibungsmechanismus, der von Spark verwendet wird. Die Daten werden zunächst in ein temporäres Verzeichnis geschrieben und nach Abschluss aller Tasks atomar an das endgültige Ziel verschoben. Weitere Informationen zu diesem Vorgang finden Sie unter Grund für die temporäre Erstellung von Spark _

Damit dieser Prozess erfolgreich ist, benötigen Sie ein gemeinsam genutztes Dateisystem (HDFS, NFS usw.) oder einen gleichwertigen verteilten Speicher (wie S3). Da Sie keinen haben, wird erwartet, dass der temporäre Status nicht bereinigt werden kann - Das Speichern von Datenrahmen im lokalen Dateisystem führt zu leeren Ergebnissen .

Das von Ihnen beobachtete Verhalten (teilweise festgeschriebene und teilweise nicht festgeschriebene Daten) kann auftreten, wenn sich einige Ausführer neben dem Treiber befinden und das Dateisystem mit dem Treiber gemeinsam nutzen, wodurch die vollständige Festschreibung für die Teilmenge der Daten aktiviert wird.

3
user6910411

Mehrere Teiledateien basieren auf Ihrer Datenframe-Partition. Die Anzahl der geschriebenen Dateien oder Daten hängt von der Anzahl der Partitionen ab, über die der DataFrame zum Zeitpunkt des Schreibens der Daten verfügt. Standardmäßig wird eine Datei pro Partition der Daten geschrieben.

sie können dies durch Zusammenführen oder Aufteilen steuern. Sie können die Partition verkleinern oder vergrößern.

wenn Sie 1 zusammenführen, werden nicht mehrere Teiledateien darin angezeigt, dies wirkt sich jedoch auf das parallele Schreiben von Daten aus.

[outputDirPath = /tmp/multiple.csv]

dataframe
 .coalesce(1)
 .write.option("header","false")
 .mode(SaveMode.Overwrite)
 .csv(outputDirPath);

auf Ihre Frage, wie man es bezieht ..

beziehen Sie sich für alle folgenden Teile auf /tmp/multiple.csv.

/tmp/multiple.csv/part-00000.csv
/tmp/multiple.csv/part-00001.csv
/tmp/multiple.csv/part-00002.csv
/tmp/multiple.csv/part-00003.csv
2
Karthick