在Spark应用程序中保存RDD的元素

时间:2016-06-21 20:02:06

标签: apache-spark pyspark rdd

我正在群集上运行spark应用程序。我想对RDD中的每个元素执行一些操作,并将每个元素保存到文本文件中。

我在myRDD上呼叫foreach

  myRDD.foreach(process)

   def process(elements):
        // some operation that extracts the strings
        // and converts to myList
        myList = ... 

        with open("somefile.txt", "a+") as myfile:
            print "----SAVED----"
            myfile.writelines(myList)

但是,即使我发现打印语句没有任何错误/警告,我也找不到somefile.txt。 somefile.txt在哪里保存?如果我的方法不正确,我如何保存RDD的各个元素?

2 个答案:

答案 0 :(得分:2)

好的,所以这个问题的原因是RDD不一定在单个节点上。致电foreach时,您的RDD分布在您的节点上。您需要使用collectuse the built in file writer, but this won't modify it.

将RDD收集到驱动程序节点

collect可能会更好,但它也会出现瓶颈,因为现在所有数据都被收集到一个节点(驱动程序节点)中。

编辑:我将用一些代码回答你的其他问题......

def process(element):
  #process element to a list
  return myList

def writeList(myList):
  with open('somefile.txt', 'a+') as f:
    f.writelines(myList)

#in main
myListRDD = myRDD.map(process)
myListRDD.collect().foreach(writeList)

这应该做到你想要的效率。因为我们处理列表的新RDD,所以我们能够并行执行所有处理,因此唯一的线性操作是文件写入,需要在单个节点上进行数据一致性。

答案 1 :(得分:2)

myRDD.map(convertToList).saveAsTextFile(<hdfs output path>)

使用这种方法,您将能够扩展您的应用程序,如果您必须将所有数据传输到驱动程序中,那么您将保证输出数据足够小以适应驱动程序内存,否则您将开始遇到麻烦。

如果您要求所有数据只在一个文件中结束(那么这种方法与将所有输出传输到驱动程序的问题类似,不可扩展):

myRDD.map(generateList).coalesce(1).saveAsTextFile(<hdfs output path>)

如果您需要在将列表存储在文件中之前将其转换为字符串,那么:

myRDD.map(generateList).map(listToString).saveAsTextFile(<hdfs output path>)

显然,您可以将列表转换为第一个地图中的字符串,并节省额外的步骤。