YARN 上 Spark 应用程序的物理内存使用量不断增加

G_c*_*_cy 5 hadoop memory-management apache-spark

我在 YARN 客户端模式下运行一个 Spark 应用程序,有六个执行器(每个有四个内核和执行器内存 = 6 GB 和开销 = 4 GB,Spark 版本:1.6.3 / 2.1.0)。

我发现我的 executor 内存一直在增加,直到被节点管理器杀死;它给出了告诉我要提升的信息spark.yarn.excutor.memoryOverhead

我知道这个参数主要控制堆外分配的内存大小。但我不知道 Spark 引擎何时以及如何使用这部分内存。同样增加那部分内存并不总能解决我的问题。有时它有效,有时无效。当输入数据很大时,它趋于无用。

仅供参考,我的应用程序的逻辑非常简单。就是把一天(一天一个目录)生成的小文件合并成一个,写回HDFS。下面是核心代码:

val df = spark.read.parquet(originpath)
              .filter(s"m = ${ts.month} AND d = ${ts.day}")
              .coalesce(400)
val dropDF = df.drop("hh").drop("mm").drop("mode").drop("y").drop("m").drop("d")

dropDF.repartition(1).write
      .mode(SaveMode.ErrorIfExists)
      .parquet(targetpath)
Run Code Online (Sandbox Code Playgroud)

源文件可能有数百到数千个级别的分区。总镶木地板文件大约为 1 到 5 GB。

另外我发现在从不同机器shuffle读取数据的步骤中,shuffle read的大小大约是输入大小的四倍,这是有线的还是一些我不知道的原理。

无论如何,我已经对这个问题进行了一些搜索。有文章说是在直接缓冲内存上(我自己没设置)。

有些文章说人们用更频繁的full GC来解决它。

另外,我在 Stack Overflow 上发现一个人的情况非常相似:YARN 中的 Spark 应用程序的物理内存不断增加

这家伙声称这是镶木地板的错误,但评论质疑他。此邮件列表中的人也可能在几个小时前收到 blondowski 发来的电子邮件,他在编写 JSON 时描述了这个问题:Executors - running out of memory

因此,对于不同的输出格式,这似乎是常见问题。

我希望有这方面经验的人可以对这个问题做出解释。为什么会发生这种情况以及解决此问题的可靠方法是什么?

G_c*_*_cy 1

这几天我只是和同事一起做了一些调查。我的想法是这样的:从spark 1.2开始,我们使用具有堆外内存的Netty来减少shuffle和缓存块传输期间的GC。就我而言,如果我尝试将内存开销增加得足够大。我将得到最大直接缓冲区异常。当Netty进行块传输时,默认会有5个线程来抓取数据块到目标执行器。在我的情况下,单个块太大而无法放入缓冲区。所以 gc 不会\xe2\x80\x99 在这里提供帮助。我的最终解决方案是在重新分区(1)之前再进行一次重新分区。只是为了使分区比原来的\xe2\x80\x99s多10倍。通过这种方式,我可以减少Netty传输的每个chunk的大小。就这样我终于成功了。

\n\n

我还想说,将大数据集重新分区到单个文件中并不是一个好的选择。这种极度不平衡的情况会浪费您的计算资源。

\n\n

欢迎大家评论,这部分我还是不太明白。

\n