在任务执行期间序列化在Spark执行程序中创建的临时集合

时间:2017-01-11 10:25:33

标签: scala apache-spark distributed-computing

我正在尝试找到一种有效的方法,将在任务中创建的集合写入作业的输出文件。例如,如果我们使用foreach迭代RDD,我们可以在以下代码片段中创建对于执行者({1}}本地的数据结构。我的问题是如何序列化ListBuffer arr并将其写入文件? (1)我应该使用arr api还是Spark FileWriter会起作用? (2)使用一个优于另一个的优点是什么 (3)有没有更好的方法来实现同样的目标。

PS:我使用saveAsTextFile而不是foreach的原因是因为我可能无法转换所有RDD行,并且我希望避免在输出中获取Null值。

map

谢谢, Devj

2 个答案:

答案 0 :(得分:3)

你不应该使用驱动程序的变量,但是累加器 - 以及关于它们的文章,代码示例hereherethis问题也许有用 - 简化了自定义select distinct columnA + [Column_in_question] from [dbo].[Tabled_in_question]

的代码示例

编写您自己的累加器,可以添加AccumulatorParam或使用内置CollectionAccumulator。这是来自Spark 2的新版累加器AccumulatorV2的实现

其他方式是使用Spark内置过滤器和地图功能 - 感谢@ImDarrenG建议flatMap,但我认为过滤器和地图会更容易:

(String, String)

答案 1 :(得分:2)

Spark API为您节省了一些文件处理代码,但基本上可以实现相同的目的。

例外情况是,如果您不使用HDFS,并且不希望对输出文件进行分区(遍布执行程序文件系统)。在这种情况下,您需要将数据收集到驱动程序并使用FileWriter写入单个文件或文件,以及您实现的方式取决于您拥有的数据量。如果你有比驱动程序有更多内存的数据,你将需要以不同的方式处理它。

正如另一个答案中所提到的,您在驱动程序中创建一个数组,同时添加执行程序中的项目,这些项目在集群环境中无效。这样的事情可能是映射数据和处理空值的更好方法:

val outputRDD = dataSorted.flatMap {
    case (e, r) => {
        if(e.id > 1000) {
            Some(("a", "b"))
        } else {
            None
        }
    }
 }
 // save outputRDD to file/s here using the approapriate method...