Apache spark Spark写入CSV即使在8小时后也会失败

Apache spark Spark写入CSV即使在8小时后也会失败,apache-spark,spark-dataframe,Apache Spark,Spark Dataframe,我有一个数据框,其中包含大约200-600 gb的数据,我正在使用elastic map reduce集群上的spark shell(scala)读取、处理并写入csv。spark写入csv即使在8小时后也会失败 以下是我写csv的方式: result.persist.coalesce(20000).write.option("delimiter",",").csv("s3://bucket-name/results") 结果变量是通过混合一些其他数据帧中的列创建的: var result=s

我有一个数据框,其中包含大约200-600 gb的数据,我正在使用elastic map reduce集群上的
spark shell(scala)
读取、处理并写入csv。spark写入csv即使在8小时后也会失败

以下是我写csv的方式:

result.persist.coalesce(20000).write.option("delimiter",",").csv("s3://bucket-name/results")
结果变量是通过混合一些其他数据帧中的列创建的:
var result=sources.join(destinations,Seq(“source\u d”,“destination\u d”))。选择(“source\u i”,“destination\u i”)

现在,我能够在大约22分钟内读取它所基于的csv数据。在这个程序中,我还能够在8分钟内将另一个(较小的)数据帧写入csv。然而,对于这个
结果
数据帧,它需要8个多小时,仍然失败。。。说其中一个连接已经关闭

我还在ec2上的13 x c4.8X大型实例上运行此作业,每个实例有36个内核和60 gb的ram,因此我认为我有能力写入csv,特别是在8小时后

很多阶段都需要重试,或者任务失败,我不知道自己做错了什么,为什么要花这么长时间。我可以从Spark UI中看到,它甚至从未进入写入CSV阶段,并且一直忙于持久化阶段,但如果没有持久化功能,它在8小时后仍然失败。有什么想法吗?非常感谢您的帮助!

更新:

我已运行以下命令将
结果
变量重新划分为66K个分区:

val r2 = result.repartition(66000) #confirmed with numpartitions
r2.write.option("delimiter",",").csv("s3://s3-bucket/results")
然而,即使几个小时后,这些工作仍在失败。我到底做错了什么

注意,我正在通过
sparkshell纱线--driver memory 50G运行sparkshell

更新2:

我已尝试先使用persist运行write:

r2.persist(StorageLevel.MEMORY_AND_DISK)
但是我有很多阶段失败,返回一个,
作业由于阶段失败而中止:ShuffleMapStage 10(持续时间:36)失败的次数达到了允许的最大次数:4。最新的失败原因:org.apache.spark.shuffle.MetadataFetchFailedException:缺少shuffle 3'
的输出位置,或者说ip-172-31-48-180.ec2.internal/172.31.48.180:7337已关闭

执行人页面

返回洗牌错误的节点的Spark web UI页面

返回ec2连接关闭错误的节点的Spark web UI页面

总体工作总结页面

我可以从Spark用户界面上看到,它甚至从未写入CSV 阶段,并忙于持久化阶段,但没有持久化 8小时后,功能仍在失效。有什么想法吗

也就是说,无法获取洗牌块

因为你能够处理小文件,只有大数据它失败了。。。 我强烈感到分区不够

首先是验证/打印
source.rdd.getNumPartitions()
。和
destinations.rdd.getNumPartitions()
。和
result.rdd.getNumPartitions()

加载数据后需要重新分区,以便将数据(通过随机播放)分区到集群中的其他节点。这将为您提供所需的并行性,以加快处理速度而不会出现输出故障

此外,为了验证应用的其他配置。。。 像这样打印所有配置,根据需要将其调整为正确的值

sc.getConf.getAll
也看看
  • 可能的原因:OOM或容器内存限制

在加入之前重新分区源和目标,分区数量为10MB-128MB(尝试调整),无需将其设置为20000(imho太多)。 然后通过这两列连接,然后写入,而不进行重新分区(即,输出分区应与连接前的重新编写相同)


如果您仍然有问题,请在将两个数据帧转换为rdd后尝试做相同的事情(API之间存在一些差异,尤其是在重新分区、键值rdd等方面)

这感觉像笛卡尔连接,不是吗?您必须在ec2中编写小文件。我猜您正在尝试一次写入整个数据。您在对Ram的响应中写道,
source
dest
中有200个分区,但没有在
result
中打印分区数-有多少个?还有,笛卡尔连接产生了什么样的通货膨胀?10倍?100倍?1000x?我的错误Tim-结果中也有200个分区。正如我在更新中提到的,使用重新分区,我将其增加到66K个分区。至于通胀,我如何衡量呢?源和目标都有相同数量的对应行,因此结果数据帧最终是相同数量的行,但每个行有2列,以防延迟,我将很快尝试您的建议这是我得到的输出:scala>sources.rdd.getNumPartitions res25:Int=200 scala>destinations.rdd.getNumPartitions res26:Int=200 getAll命令的输出:。。。我尝试过重新分区和合并函数,但由于某些原因,它总是返回200。知道它为什么不起作用吗?