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
因此,对于不同的输出格式,这似乎是常见问题。
我希望有这方面经验的人可以对这个问题做出解释。为什么会发生这种情况以及解决此问题的可靠方法是什么?
这几天我只是和同事一起做了一些调查。我的想法是这样的:从spark 1.2开始,我们使用具有堆外内存的Netty来减少shuffle和缓存块传输期间的GC。就我而言,如果我尝试将内存开销增加得足够大。我将得到最大直接缓冲区异常。当Netty进行块传输时,默认会有5个线程来抓取数据块到目标执行器。在我的情况下,单个块太大而无法放入缓冲区。所以 gc 不会\xe2\x80\x99 在这里提供帮助。我的最终解决方案是在重新分区(1)之前再进行一次重新分区。只是为了使分区比原来的\xe2\x80\x99s多10倍。通过这种方式,我可以减少Netty传输的每个chunk的大小。就这样我终于成功了。
\n\n我还想说,将大数据集重新分区到单个文件中并不是一个好的选择。这种极度不平衡的情况会浪费您的计算资源。
\n\n欢迎大家评论,这部分我还是不太明白。
\n| 归档时间: |
|
| 查看次数: |
1189 次 |
| 最近记录: |