YARN 上 Spark 应用程序的物理内存使用量不断增加
Posted
技术标签:
【中文标题】YARN 上 Spark 应用程序的物理内存使用量不断增加【英文标题】:Physical memory usage keeps increasing for Spark application on YARN 【发布时间】:2017-01-22 09:43:13 【问题描述】:我正在 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)
源文件可能有成百上千级的分区。 Parquet 文件的总大小约为 1 到 5 GB。
另外我发现在shuffle从不同机器读取数据的步骤中,shuffle read的大小大约是输入大小的4倍,这是连线还是什么原理我不知道。
无论如何,我已经为这个问题做了一些搜索。有文章说是在直接缓冲内存上(我自己没设置)。
有人说人们用更频繁的full GC来解决它。
另外,我在 *** 上发现一个人的情况非常相似:Ever increasing physical memory for a Spark application in YARN
这家伙声称这是镶木地板的错误,但有评论质疑他。此邮件列表中的人也可能在数小时前收到一封来自 blondowski 的电子邮件,他在编写 JSON 时描述了此问题:Executors - running out of memory
所以对于不同的输出格式来说,这似乎是一个常见的问题。
我希望有此问题经验的人可以对此问题进行解释。为什么会发生这种情况以及解决此问题的可靠方法是什么?
【问题讨论】:
我首先要说repartition(1)
和/或 coalesce(1)
在 Spark 中主要是反模式,除非您的数据非常小,然后您可以收集结果并以通常的方式写入.
@eliasah 还有其他有效的方法来完成我的组合工作吗?
为什么要把所有东西都放在一个 parquet 文件中?
@eliasah 实际上,我知道这会是个问题。但组长确定每天只有一个文件。另外,我希望知道为什么引擎会返回堆外内存的信息。 THX
这是问题所在。在 1 到 5G 之间拥有一个文件是分布式环境中的另一个巨大反模式。换句话说,就是不要这样做。
【参考方案1】:
这几天我只是和我的同事做一些调查。这是我的想法:从 spark 1.2 开始,我们使用带有堆外内存的 Netty 来减少 shuffle 和缓存块传输期间的 GC。就我而言,如果我尝试将内存开销增加得足够大。我将得到最大直接缓冲区异常。 Netty 在做阻塞传输时,默认会有五个线程去抓取数据块到目标执行器。在我的情况下,一个块太大而无法放入缓冲区。所以 gc 在这里帮不上忙。我的最终解决方案是在重新分区(1)之前进行另一个重新分区。只是为了制作比原来多 10 倍的分区。这样,我就可以减少Netty传输的每个chunk的大小。这样我终于成功了。
另外我想说的是,将大数据集重新分区为单个文件不是一个好的选择。这种极其不平衡的情况有点浪费您的计算资源。
欢迎评论,这部分我还是不太明白。
【讨论】:
以上是关于YARN 上 Spark 应用程序的物理内存使用量不断增加的主要内容,如果未能解决你的问题,请参考以下文章