Hadoop .20数据节点出现“GC Overhead limit exceeded”错误

10
我搜索了很多与Hadoop数据节点因GC超时限制而死亡的相关信息,但是没有找到太多,所以我想发布一个问题。我们正在运行一个测试,需要确认我们的Hadoop集群可以处理存储在其上的大约3百万个文件(当前为4个节点集群)。我们使用64位JVM,并为namenode分配了8g。然而,当我的测试程序将更多文件写入DFS时,数据节点开始死机,并显示以下错误: Exception in thread "DataNode:[/ var / hadoop / data / hadoop / data]" java.lang.OutOfMemoryError:GC overhead limit exceeded
我看到一些帖子提到了一些选项(parallel GC?),我猜这些可以在hadoop-env.sh中设置,但我不太确定语法,而且我有点新手,所以我没太明白怎么做。感谢您在这里提供的任何帮助!

这里是关于更新的提示:在我的dfs中有150万个文件,当我的64位JVM设置为1g(默认值)时,数据节点开始出现错误并不断死亡。当我将其提高到2g时,出现的问题消失了,直到我达到了大约300万个文件。我想知道这种内存膨胀是否是一个已知的问题,如果是,那么我可以尝试哪些其他建议来解决它? - hatrickpatrick
像Tejas Patil所提到的那样,默认块大小是64MB。每次运行Hadoop时,它会将每个文件的元数据加载到内存中。您拥有的文件越多,它占用的内存就越多。如果这些文件远小于默认块大小,并且您有该选项,请尝试将文件合并为更大的文件,以存储到HDFS中。只是一个想法 :) - sufinawaz
4个回答

11

尝试通过以下方式增加数据节点的内存:(需要重新启动hadoop才能生效)

export HADOOP_DATANODE_OPTS="-Xmx10g"

这将把堆设置为10GB...您可以根据需要增加。

您还可以将此粘贴到$HADOOP_CONF_DIR/hadoop-env.sh文件的开头。


2
这基本上解决了问题,但我也学到了当你在一个小集群上存储大量文件时,DataNode 的使用率会迅速攀升,因为复制只能发生在有限的位置。如果我们添加节点,那么数据节点内存不应该那么快地攀升(据说!)。 - hatrickpatrick
2
@hatrickpatrick HDFS使用64 MB块进行文件存储...如果文件很小,那么会浪费很多内存,甚至namenode也必须跟踪这些文件。拥有少量但是巨大的文件比拥有许多小文件更好。 - Tejas Patil
HADOOP_DATANODE_OPTS 的默认 -Xmx 是多少? - Sida Zhou
默认值为200m。 - Sida Zhou

0

如果您正在从命令行运行MapReduce作业,可以使用参数-D 'mapreduce.map.java.opts=-Xmx1024m'和/或-D 'mapreduce.reduce.java.opts=-Xmx1024m'来增加堆大小。示例:

hadoop --config /etc/hadoop/conf jar /usr/lib/hbase-solr/tools/hbase-indexer-mr-*-job.jar --conf /etc/hbase/conf/hbase-site.xml -D 'mapreduce.map.java.opts=-Xmx1024m' --hbase-indexer-file $HOME/morphline-hbase-mapper.xml --zk-host 127.0.0.1/solr --collection hbase-collection1 --go-live --log4j /home/cloudera/morphlines/log4j.properties

请注意,在一些Cloudera文档中,他们仍然使用旧的参数mapred.child.java.optsmapred.map.child.java.optsmapred.reduce.child.java.opts。这些参数在Hadoop 2中不再起作用(请参见Apache Hadoop YARN中'mapreduce.map.memory.mb'和'mapred.map.child.java.opts'之间的关系是什么?)。

0

这个帖子解决了我的问题。

所以,关键是要“在环境变量前面添加”(第一次看到这种Linux命令语法 :))

HADOOP_CLIENT_OPTS="-Xmx10g" hadoop jar "your.jar" "source.dir" "target.dir"

-2

GC overhead limit 表示你的(微小)堆已满。

这在 MapReduce 操作中处理大量数据时经常发生。尝试以下方法:

< property >

  < name > mapred.child.java.opts < /name >

   < value > -Xmx1024m -XX:-UseGCOverheadLimit < /value >

< /property >

另外,也可以尝试以下这些内容:

使用 combiners,reducers 不应该得到任何比 map 数量的小倍数更长的列表

同时,您可以从 OOME 生成堆转储,并使用 YourKit 等进行分析。


@ThomasJungblut +1。mapred.child.java.opts 可以用于控制 Hadoop 作业生成的堆大小,而不是数据节点。 - Tejas Patil
1
好的,我没有检查过。但是,他的问题实际上有两种类型:(1)数据节点内存限制(2)中间步骤的排序等。所以,我的观点是我们不能盲目地将数据节点堆大小增加到10 GB、20 GB之类的大小,如果我们可以调整参数(如上所述)并使用组合器,我认为解决方案会很好。 - shiva kumar s

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