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

时间:2017-06-11 16:11:08

标签: apache-spark spark-dataframe

我有一个大约200-600 gb数据的数据框,我正在阅读,操作,然后使用弹性地图缩小群集上的spark shell (scala)写入csv。即使在8小时后,写入CSV的Spark也会失败< / p>

这是我写给csv的方式:

result.persist.coalesce(20000).write.option("delimiter",",").csv("s3://bucket-name/results")

结果变量是通过来自其他一些数据帧的混合列创建的: var result=sources.join(destinations, Seq("source_d","destination_d")).select("source_i","destination_i")

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

我也在13 x c4.8xlarge instances on ec2上运行这个工作,每个工作36个核心和60 GB的ram,所以我认为我有能力写入csv,特别是8小时后。

许多阶段需要重试或任务失败,我无法弄清楚我做错了什么或为什么这么长时间。我可以从Spark UI看到它甚至从未进入写入CSV阶段并忙于持续阶段,但没有持久性功能,它仍然在8小时后失败。有任何想法吗?非常感谢帮助! Spark web UI

更新

我运行了以下命令将result变量重新分区为66K分区:

val r2 = result.repartition(66000) #confirmed with numpartitions
r2.write.option("delimiter",",").csv("s3://s3-bucket/results")

然而,即使在几个小时后,工作仍然失败。我到底做错了什么?

stages breakdown failed stages

请注意,我正在通过spark-shell yarn --driver-memory 50G

运行spark shell

更新2:

我尝试先使用persist执行写操作:

r2.persist(StorageLevel.MEMORY_AND_DISK)

但我有很多阶段失败,返回a,Job aborted due to stage failure: ShuffleMapStage 10 (persist at <console>:36) has failed the maximum allowable number of times: 4. Most recent failure reason: org.apache.spark.shuffle.MetadataFetchFailedException: Missing an output location for shuffle 3'或说Connection from ip-172-31-48-180.ec2.internal/172.31.48.180:7337 closed

执行人页面 Executors page

返回随机错误的节点的Spark Web UI页面 Spark web UI page for a node returning a shuffle error

返回ec2连接的节点的Spark Web UI页面已关闭错误 Spark web UI page for a node returning an ec2 connection closed error

整体职位摘要页 Overall Job Summary page

2 个答案:

答案 0 :(得分:1)

  

我可以从Spark UI看到它甚至没有写入CSV   阶段,并忙于坚持阶段,但没有坚持   功能它在8小时后仍然失败。有什么想法吗?

enter image description here

FetchFailedException,即无法获取随机块

由于你能够处理小文件,只有大量数据失败... 我强烈感觉没有足够的分区。

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

您需要在加载数据后重新分区,以便将数据(通过shuffle)分区到群集中的其他节点。这将为您提供快速处理失败所需的并行性

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

sc.getConf.getAll

还看看

答案 1 :(得分:0)

在加入之前重新分配源和目标,分区数量使每个分区为10MB - 128MB(尝试调整),没有必要使它20000(imho太多)。 然后通过这两列连接然后写入,而不进行重新分区(即输出分区应该与连接前的重新分区相同)

如果你还有问题,请在转换为数据帧到rdd之后尝试做同样的事情(apis之间存在一些差异,特别是关于重新分区,键值rdds等)