了解Spark shuffle溢出

9
如果我理解正确,当reduce任务开始收集其输入shuffle块(来自不同map任务的输出)时,它首先将它们保存在内存中(Q1)。在执行器的shuffle-reserved内存量用尽之前(在内存管理改变之前(Q2)),内存中的数据会被“溢写”到磁盘中。如果spark.shuffle.spill.compress为true,则该内存中的数据会以压缩方式写入磁盘。
我的问题:
Q0:我的理解正确吗?
Q1:reduce任务收集的数据是否总是未压缩的?
Q2:如何估计可用于收集shuffle块的执行器内存量?
Q3:我看到过“shuffle溢写发生在数据集无法容纳在内存中”的说法,但据我所知,只要执行器的shuffle-reserved内存足够容纳所有其活动任务的(未压缩的)shuffle输入块,就不应该发生spill,这正确吗?
如果是这样,为了避免溢写,需要确保最终进入所有并行reduce端任务的(未压缩的)数据小于执行器的shuffle-reserved内存部分吗?

你使用的是1.6之前的哪个确切版本的Spark?为什么不能使用1.6.1? - Sim
我的大部分问题(除了与洗牌相关的内存大小以外)都是通用的,不依赖于具体的版本。我在生产中使用1.3.1版本,因为这是EMR AMIs上可用的版本。新版本EMR(发布标签)上有1.6.1版本可供我进行实验,但尚未投入生产使用。 - Harel Gliksman
我强烈建议您切换到1.6.1版本。在Spark标准中,1.3.1版本已经过时且存在许多问题;只需查看Spark的JIRA即可了解。性能提升可能会超过您通过手动调整1.3.1版本所能达到的任何效果。 - Sim
再次,问题的目的是了解在Spark中“spill”到底是什么,因为我找不到一个清晰解释的有效资源...我提出的问题是我个人理解中的“漏洞”。我认为这对于任何使用任何Spark版本的Spark用户来说可能是相关的。 - Harel Gliksman
1
这个问题对于使用任何Spark版本的用户都不相关,因为内存管理的内部机制差异很大。如果你想了解spill是什么基础知识,请阅读这篇文章:https://dev59.com/w1wY5IYBdhLWcg3wyqWH - Sim
1个回答

6
在1.6之前和之后的内存管理方面有所不同。在两种情况下,都有执行内存和存储内存的概念。区别在于,在1.6之前是静态的。这意味着有一个配置参数指定了执行和存储所需的内存量。如果其中一个不够用,就会有溢出的情况。
Apache Spark需要解决的问题之一是并发执行:
- 并行执行的不同阶段 - 不同任务,如聚合或排序。
内存中的内容是未压缩的,否则无法处理。执行内存以块状形式溢出到磁盘上,并且像您提到的那样可以进行压缩。自1.3.1以来,您可以进行配置,然后确定大小。在任何时刻剩余的内容,您可以通过查看类似于jstat -gcutil <pid> <period>的执行器进程来了解。它可能会为您提供有关可用内存的线索。知道存储和执行的内存量后,尽可能少使用default.parallelism可能会给您提供线索。这是正确的,但很难理解;数据可能存在偏移,例如某些键具有比其他键更多的值,同时也有许多并行执行等。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接