为什么Spark会在shuffle发生时使用并占用太多内存?

时间:2017-01-06 13:17:07

标签: memory apache-spark shuffle

我发现在Spark进程中发生shuffle时内存使用量太多了。

下图是使用700MB数据和三个rdd.map时的内存指标。 (我使用Ganglia作为监控工具,只显示我的集群的三个节点.x轴表示时间序列,y轴表示内存使用)

enter image description here

以下图也是当我使用相同数据并使用三个rdd.groupBy,三个rdd.flatMap(顺序:groupBy1-> flatMap1-> groupBy2-> flatMap2-> groupBy3-> flatMap3)时的内存指标)

enter image description here

正如您所看到的,即使我只使用700MB数据,三个节点的所有内存都会大幅增加(几GB)。实际上我有8个工作节点,并且所有8个工人的内存都大大增加了。

我认为主要原因是洗牌,因为rdd.map没有shuffle但是rdd.groupBy已经洗牌。

在这种情况下,我想知道以下三点:

  1. 为什么内存使用量过多? (当我在所有工作节点中使用700MB时,使用超过15GB。)
  2. 为什么在Spark应用程序完成之前,似乎没有删除用于旧shuffle的已用内存?
  3. 有没有办法减少内存使用量或删除旧shuffle中生成的内存?
  4. P.S。 - 我的环境:

    1. 云平台:MS Azure(8个工作节点)
    2. 规格。一名工人:8核CPU,16GB RAM
    3. 语言:Java
    4. Spark版本:1.6.2
    5. Java版本:1.7(开发),1.8(执行)
    6. 在Spark-standalone中运行(不使用Yarn或Mesos)

1 个答案:

答案 0 :(得分:0)

在Spark中,操作系统将决定数据是否可以保留在缓冲区缓存中,还是应该溢出到DISK。每个map任务都会创建与reducers数量一样多的shuffle溢出文件。 SPARK没有合并并将shuffle溢出文件分区为一个大文件,Apache Hadoop就是这种情况。 示例:如果有6000(R)缩减器和2000(M)映射任务,则会有(M * R)6000 * 2000 = 1200万个shuffle文件。这是因为,在spark中,每个map任务都会创建与reducers数量一样多的shuffle溢出文件。这导致性能下降。

请参阅Optimizing Shuffle Performance in Spark帖子,在上述说明的继续中详细解释了这一点。

您还可以参考{{3}}论文。

〜基达