apache-spark - 为什么一个非常大的 Spark 阶段不使用所有可用的执行器?
问题描述
我正在运行一个包含一些非常大的阶段(例如 >20k 任务)的 Spark 作业,并且正在使用 1k 到 2k 执行器运行它。
在某些情况下,一个阶段似乎运行不稳定:许多可用的执行器随着时间的推移变得空闲,尽管仍然处于一个有许多未完成任务的阶段的中间。从用户的角度来看,任务似乎正在完成,但是已经完成给定任务的执行者不会获得分配给他们的新任务。结果,该阶段花费的时间超出了应有的时间,并且大量执行程序 CPU 小时被浪费在空闲上。这似乎主要(仅?)发生在从 HDFS 读取数据的输入阶段。
不稳定时期的 Spark stderr 日志示例 - 请注意,正在运行的任务数量会随着时间的推移而减少,直到几乎达到零,然后突然跳回到 >1k 正在运行的任务:
[Stage 0:==============================> (17979 + 1070) / 28504]
[Stage 0:==============================> (18042 + 1019) / 28504]
[Stage 0:===============================> (18140 + 921) / 28504]
[Stage 0:===============================> (18222 + 842) / 28504]
[Stage 0:===============================> (18263 + 803) / 28504]
[Stage 0:===============================> (18282 + 786) / 28504]
[Stage 0:===============================> (18320 + 751) / 28504]
[Stage 0:===============================> (18566 + 508) / 28504]
[Stage 0:================================> (18791 + 284) / 28504]
[Stage 0:================================> (18897 + 176) / 28504]
[Stage 0:================================> (18940 + 134) / 28504]
[Stage 0:================================> (18972 + 107) / 28504]
[Stage 0:=================================> (19035 + 47) / 28504]
[Stage 0:=================================> (19067 + 17) / 28504]
[Stage 0:================================> (19075 + 1070) / 28504]
[Stage 0:================================> (19107 + 1039) / 28504]
[Stage 0:================================> (19165 + 982) / 28504]
[Stage 0:=================================> (19212 + 937) / 28504]
[Stage 0:=================================> (19251 + 899) / 28504]
[Stage 0:=================================> (19355 + 831) / 28504]
[Stage 0:=================================> (19481 + 708) / 28504]
这是一个阶段稳定运行时 stderr 的样子——运行任务的数量大致保持不变,因为新任务在执行者完成之前的任务时被分配给它们:
[Stage 1:===================> (11599 + 2043) / 28504]
[Stage 1:===================> (11620 + 2042) / 28504]
[Stage 1:===================> (11656 + 2044) / 28504]
[Stage 1:===================> (11692 + 2045) / 28504]
[Stage 1:===================> (11714 + 2045) / 28504]
[Stage 1:===================> (11741 + 2047) / 28504]
[Stage 1:===================> (11771 + 2047) / 28504]
[Stage 1:===================> (11818 + 2047) / 28504]
在什么情况下会发生这种情况,我该如何避免这种行为?
注意:我正在使用动态分配,但我很确定这与这个问题无关——例如,在不稳定时期,在 Spark Application Master UI 中,我可以看到预期的执行器数量是“活动的”,但是没有运行“活动任务”。
解决方案
当每个任务花费的时间非常低时,我已经从 spark 中看到过这样的行为。出于某种原因,调度程序似乎假设作业将更快地完成而没有额外的分发开销,因为每个任务都完成得如此之快。
有几件事可以尝试:
- 尝试
.coalesce()
减少分区的数量,以便每个分区需要更长的时间来运行(当然,这可能会导致 shuffle 步骤并且可能会增加整体作业时间,您必须过期) - 在此处调整
spark.locality.wait*
设置。如果每个任务花费的时间少于默认的等待时间,那么调度程序可能只是试图保持现有的槽满,而永远没有机会分配更多的槽。3s
我还没有确切地找到导致这个问题的原因,所以这些只是基于我自己在我自己的(小得多的)集群中的观察的推测和预感。
推荐阅读
- angular - 您将如何正确使用依赖于其他请求的 GET 请求?
- excel - 嵌套 IF/COUNTBLANK/ISBLANK 公式
- java - Fileinputstream NullPointerException Java
- javascript - Uncaught SyntaxError: Invalid or unexpected token when using $(element).html to include jsp
- python - 如何将每个字符的数字表示相加
- r - 合并数据框而不更改值
- jquery - 滚动到特定部分时,我想向上移动一些像素,因为标题被持久标题隐藏
- javascript - JavaScript 中的多个返回值
- excel - 按客户计算每个位置的访问次数
- .net-core-2.2 - 我可以获得解决 .NET 4.7.2 项目的包参考的帮助吗?