Spark为什么会选择在单个节点上完成所有工作?

问题描述 投票:8回答:1

我在执行Spark作业时遇到困难,大约一半的时间,它将选择在单个节点上处理所有数据,然后该节点的内存不足并死亡。

问题:如何确保这一切都没有发生?

系统在Yarn上使用Spark 1.6.0,从Hadoop 2.6数据存储中提取数据,所有代码均用Java编写。我正在具有十几个节点(Amazon)的整个集群中动态分配资源。

DAG比较简单:

RDD --> mapToPair \  
                   coGroup --> flatMapToPair --> reduceByKey --> save
RDD --> mapToPair /

当它正确运行时,所有任务将在整个集群中得到很好的分配,整个工作大约需要20分钟。我们称其为“良好行为”。但是,有时候,flatMapToPair阶段实际上在单个执行程序中运行。我们称此为“不良行为”

[当我为一个“不良行为”工作加载Spark UI并进入flatMapToPair阶段时,我发现实际上每个节点上运行着大约3-4个执行程序(与“良好行为”相同案件)。但是,除了一个完成过程外,几乎所有的执行程序都在不到一秒钟的时间内完成,其余的执行程序将运行10分钟,然后由于超出存储限制而被纱线杀死。

我已经尝试过的事情:

  1. 网络。搜索诸如“在一个节点上运行火花”之类的内容,几乎所有版本都会导致人们在Spark Shell或类似配置问题中以本地模式运行。鉴于我至少在某些时候表现良好,所以这类配置问题似乎不太可能(并且我检查了自己是否不是偶然地处于本地模式下,我有〜100个分区,...)。

  2. 在同一群集上运行的其他Spark作业表现良好。这似乎可以排除群集范围内的某些错误配置(哎呀,即使this job有时也运行良好)。

  3. 集群利用率似乎并不会影响我获得良好行为还是不良行为。当群集被大量利用时,以及群集根本没有运行时,我都看到了这两种行为。

  4. 这似乎不是一个毛线问题,因为executors都在整个集群中分布良好。我当然对此可能是错的,但实际上问题似乎在于工作分配之间执行者。

  5. 数据集中有多个键。我在coGroup和flatMapToPair之间插入了countByKey并打印了结果(用于20个左右的人口众多的键)。数据在这些最重要的键之间相当均匀地分布。

我为回应评论而尝试过的事情

  1. 在flatMapToPair调用之前对RDD进行分区,以强制进行500个分区。这只会将不良行为转移到重新分区阶段。

  2. 增加默认的并行度。我确实通过这种方式获得了更多分区,但是不良行为仍然停留在flatMapToPair阶段。

  3. 精简数据(实际上,我在发布之前做了很多此类工作,但是未能将其包括在原始列表中)。我们只有10 GB的空间,我已经在加载所需的最低限度的数据。

这是一个“有趣”的小heisenbug,其不良行为在添加调试日志记录后消失,然后在删除日志记录后消失,直到稍后再出现。我没有主意,因此,如果有人甚至提出了一些建议的诊断步骤,我就会不知所措。

apache-spark hadoop yarn
1个回答
0
投票

我遇到了非常相似的问题,尽管我对解决方案不完全满意,因为我无法完全解释它为什么起作用,但它似乎确实起作用。就我而言,这是在改组之后,改组后的数据量很小。问题在于,随后的计算将数据的大小显着增加到一个瓶颈,即对1个或2个执行程序进行这些计算是一个瓶颈。我最好的猜测是,它与一种启发式方法有关,该启发式方法涉及数据源的首选位置和目标分区的大小,可能与后来阶段不知道发生的扩展相结合。

通过添加coalesce(totalCores),我能够获得一致,分布均匀的混洗,其中totalCores定义为spark.executor.instances x spark.executor.cores。它似乎也可以用totalCores的较大倍数工作,但就我而言,我不需要任何更多的并行性。注意,根据使用情况,可能需要使用repartition而不是coalesce。另外,这是在spark 2.2.1上进行的,以供参考。

© www.soinside.com 2019 - 2024. All rights reserved.