我正在群集上运行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的各个元素?
答案 0 :(得分:2)
好的,所以这个问题的原因是RDD不一定在单个节点上。致电foreach
时,您的RDD分布在您的节点上。您需要使用collect
或use the built in file writer, but this won't modify it.
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>)
显然,您可以将列表转换为第一个地图中的字符串,并节省额外的步骤。