如何解决由于阶段失败导致的工作中止"来自" spark.akka.framesize"?

时间:2017-05-15 06:36:44

标签: apache-spark pyspark pyspark-sql

我有一个Spark程序正在进行一系列列操作,然后调用.collect()将结果拉入内存。

我在运行代码时收到此问题:

An error occurred while calling z:org.apache.spark.api.python.PythonRDD.collectAndServe.

: org.apache.spark.SparkException: Job aborted due to stage failure: Serialized task 302987:27 was 139041896 bytes, which exceeds max allowed: spark.akka.frameSize (134217728 bytes) - reserved (204800 bytes). Consider increasing spark.akka.frameSize or using broadcast variables for large values.

这里可以看到更完整的堆栈跟踪:https://pastebin.com/tuP2cPPe

现在我想知道我需要更改为我的代码和/或配置来解决这个问题。我有一些想法:

  • 按照建议增加spark.akka.frameSize。我有点不愿意这样做,因为我不太了解这个参数,对于其他工作,我可能更喜欢默认。有没有办法在应用程序中指定它?并且可以在类似于分区数量的代码中动态地动态更改吗?

  • 在调用表上的collect()之前减少分区数。我有一种感觉,当分区太多时调用collect()会导致失败。当把所有这些碎片都拉进内存时,它会对驱动程序施加太大的压力。

我不明白这个建议Consider...using broadcast variables for large values。这有什么用?我仍然需要将结果提交给驱动程序,无论我是否有每个执行程序的数据副本。

我还缺少其他想法吗? THX。

1 个答案:

答案 0 :(得分:0)

我认为这个错误有点误导。该错误是因为您尝试下载回驱动程序的结果大于Akka(spark使用的基础网络库)可以适合消息。 广播变量用于有效发送数据到工作节点,这与您尝试的方向相反。

通常,您不想在收回大量数据时进行收集,因为您会尝试将该结果下载到一个节点,从而失去任何并行性。如果您有太多数据,这可能会永远占用或可能导致您的工作失败。您可以尝试增加Akka框架大小,直到它足够大以至于您的工作不会失败,但这可能会在您的数据增长时再次中断。

更好的解决方案是使用RDD写入API将结果保存到某些分布式文件系统(HDFS,S3)。然后,您可以使用Spark在后续作业中执行更多分布式操作,或者您可以直接从分布式文件系统下载结果,并随意执行任何操作。