HDFS和Spark:写入文件并从另一个程序重用的最佳方法

时间:2018-07-20 17:40:12

标签: apache-spark hadoop hdfs

我从保存在HDFS中的Spark应用程序得到了一些结果,文件名为part-r-0000X(X = 0、1等)。而且,因为我想将整个内容合并到一个文件中,所以我使用以下命令:

hdfs dfs -getmerge srcDir destLocalFile

上一个命令在bash脚本中使用,该脚本将输出目录清空(保存part-r-...文件的位置),并在循环内执行上面的getmerge命令。

问题是我需要在另一个Spark程序中使用生成的文件,该程序需要将该合并的文件作为HDFS中的输入。因此,我将其保存为本地,然后将其上传到HDFS。

我想到了另一个选择,可以通过这种方式从Spark程序写入文件:

outputData.coalesce(1, false).saveAsTextFile(outPathHDFS)

但是我已经读到coalesce()对性能没有帮助。

还有其他想法吗?建议?谢谢!

3 个答案:

答案 0 :(得分:2)

我想,您希望将所有文件合并到一个文件中,以便可以一次将所有文件加载到Spark rdd中。

让文件位于HDFS的Parts(0,1,....)中。

为什么不使用WholetextFiles加载它,实际上可以完成您需要的操作。

wholeTextFiles(path, minPartitions=None, use_unicode=True)[source]

从HDFS,本地文件系统(在所有节点上都可用)或任何Hadoop支持的文件系统URI中读取文本文件目录。每个文件都作为一条记录读取,并以键值对的形式返回,其中键是每个文件的路径,值是每个文件的内容。

如果use_unicode为False,则字符串将保持为str(编码为utf-8),这比unicode更快且更小。 (在Spark 1.2中添加)

例如,如果您具有以下文件:

hdfs:// a-hdfs-path / part-00000 hdfs:// a-hdfs-path / part-00001 ... hdfs:// a-hdfs-path / part-nnnnn

执行rdd = sparkContext.wholeTextFiles(“hdfs://a-hdfs-path”),然后rdd包含:

(a-hdfs-path / part-00000,其内容)(a-hdfs-path / part-00001,其内容)...(a-hdfs-path / part-nnnnn,其内容)

答案 1 :(得分:1)

尝试使用SPARK Bucket。

这是通过df.write.saveAsTable()提供的一项很好的功能,但是此格式只能由SPARK读取。数据显示在Hive Metastore中,但Hive IMPALA无法读取。

答案 2 :(得分:0)

到目前为止,我发现的最佳解决方案是:

outputData.saveAsTextFile(outPath, classOf[org.apache.hadoop.io.compress.GzipCodec])

outputData保存在part-0000X.gz目录下的压缩outPath文件中。

然后,它从另一个Spark应用程序使用以下命令读取这些文件:

val inputData = sc.textFile(inDir + "part-00*", numPartition)

inDir对应于outPath的地方。