我一直试图获得一个火花工作,现在已经运行完成几天了,我终于能够完成它了但仍然有大量失败的任务,其中执行者被杀死了以下消息:
ExecutorLostFailure(执行者77退出由其中一个正在运行的任务引起)原因:容器被YARN杀死超过内存限制。使用45.1 GB的44.9 GB物理内存。考虑提升spark.yarn.executor.memoryOverhead
这些是我传递给集群的属性:
[
{
"classification": "spark-defaults",
"properties": {
"spark.executor.memory": "41000m",
"spark.driver.memory": "8000m",
"spark.executor.cores": "6",
"spark.shuffle.service.enabled": "true",
"spark.executor.instances": "98",
"spark.yarn.executor.memoryOverhead": "5000"
}
}
]
该集群包含20台机器,每台机器有32个内核和240G内存。我是否应该继续提高memoryOverhead,或者是否表明存在更深层次的问题。在将结果数据写入S3之前,此时的错误似乎发生在从5000个分区合并到500个分区期间。我猜测coalesce引起了一次洗牌,因为集群内存已经很低,所以它推得太远了。
工作流程如下:
使用下面的combineByKey,基本上按键将各个对象合并为对象数组
combineByKey(新函数,添加函数,合并函数,新HashPartitioner(5000),false,null);
更多地图
另一个问题是如何推导出上面的44.9数字。我认为最大内存将是执行程序内存+ memoryOverhead,这将是46G而不是44.9G。
任何帮助将不胜感激, 内森
答案 0 :(得分:6)
根据我的经验,这表明存在更深层次的问题,而且从你发布的内容中我发现了一些陷阱。
首先,您可能需要查看分区大小,因为在combineByKey
操作期间创建的数据偏差很容易导致OOM。也许有些钥匙非常频繁?
如果没有,我会查看coalesce
函数调用。你还没有发布代码,所以我只能猜测正在生成的DAG,但我会知道coalesce
函数以及在同一个写阶段执行的其他操作。
Spark分阶段执行,根据我的解释,你可以在coalesce
之前调用write
,这取决于你进入最后阶段的分区数量,并取决于转换在这个阶段完成,您实际上可能在比所需更少的分区上运行,从而导致OOM异常。
用文字解释有点复杂,但我会尝试举例说明可能发生的事情。
想象一下这样一个简单的场景:你在一个文件中读取了(Int, Double)
的键值对,然后你将一些函数应用于所有的值,比如说round
。然后,您希望将输出写回单个文件,因此您调用coalesce(1)
,然后调用write
。代码看起来像这样:
val df = sqlContext.read.parquet("/path/to/my/file/")
df.map{case(key: Int, value: Double) => (key, round(value)}
.toDF()
.coalesce(1)
.write
.parquet("/my/output/path/")
现在有人可能认为map
操作是在整个集群上并行执行的,但是如果你注意spark ui,你会注意到这个任务没有在你的集群中分布。由于coalesce(1)
,Spark知道所有内容都需要在一个分区中结束,所以它只是开始将所有数据收集到应用map
函数的一个分区中。正如您可能想象的那样,这很容易在OOM异常中以更复杂的转换结束。
我希望这能为您提供一些关于在哪里寻找的指示。祝你好运:)