我正在探索Spark。我面临以下任务 - 获取RDD,根据特定条件对其进行分区,然后在S3存储桶中的不同文件夹中写入多个文件。
在我们上传到S3部分之前,一切都很好。我已经在SO上阅读了所有与此问题相关的问题,并发现我可以使用AmazonS3Client
或saveToTextFile
方法进行RDD。我面临两个问题:
如果我使用AmazonS3Client
,我会得到一个java.io.NotSerializableException
,因为代码是从Spark驱动程序发送给工作人员的,所以需要对其进行序列化,显然AmazonS3Client并不是这样。支持那个。
如果我选择saveToTextFile
,我会面临类似的问题。当我进入foreachPartition
循环时,我需要Iterable[T]
(在本例中为p
),所以如果我想使用saveToTextFile
,我需要创建一个RDD因此可以转移parallelize
。问题是SparkContext sc
也是(理所当然地)没有序列化。
rdd.foreachPartition { p =>
sc.parallelize(p.toSeq).saveAsTextFile(s"s3n://")
}
非常感谢任何帮助。
答案 0 :(得分:5)
没有必要这样做。您可以将saveAsTextFile
与rdd:
rdd.saveAsTextFile(s"s3n://dir/to/aux/file")
saveAsTextFile
将在包含文件许多部分的文件夹中写入S3(与分区一样多的部分)。然后,如果需要,您可以合并到单个文件:
def mergeToS3(srcPath: String, dstPath: String, sc: SparkContext): Unit = {
val hadoopConfig = sc.hadoopConfiguration
val fs = FileSystem.get(new URI(srcPath), hadoopConfig)
FileUtil.copyMerge(fs, new Path(srcPath), fs, new Path(dstPath), true, hadoopConfig, null)
}
mergeToS3("s3n://dir/to/aux/file", "s3n://dir/to/singleFile",sc)