关注公众号:大数据技术派,回复“资料”,领取资料,学习大数据技术。
一、Mapper/Reducer阶段JVM内存溢出(通常是堆内存溢出)
- JVM堆(Heap)内存溢出
堆内存不足时,一般会抛出如下异常:
- 第一种:“java.lang.OutOfMemoryError:” GC overhead limit exceeded;
- 第二种:“Error: Java heapspace”异常信息;
- 第三种:“running beyond physical memory limits.Current usage: 4.3 GB of 4.3 GBphysical memoryused; 7.4 GB of 13.2 GB virtual memory used. Killing container”。
1) GC overhead limit exceeded
| 参数名称 | 默认值 | 描述 |
|---|---|---|
| mapred.child.java.opts | -Xmx200m | 定义mapreduce执行的container容器的执行jvm参数 |
| mapred.map.child.java.opts | 单独指定map阶段的执行jvm参数 | |
| mapred.reduce.child.java.opts | 单独指定reduce阶段的执行jvm参数 | |
| mapreduce.admin.map.child.java.opts | -Djava.net.preferIPv4Stack=true -Dhadoop.metrics.log.level=WARN | 管理员指定map阶段执行的jvm参数 |
| mapreduce.admin.reduce.child.java.opts | -Djava.net.preferIPv4Stack=true -Dhadoop.metrics.log.level=WARN | 管理员指定reduce阶段的执行jvm参数 |
上述五个参数生效的分别执行顺序为:
map阶段:mapreduce.admin.map.child.java.opts < mapred.child.java.opts < mapred.map.child.java.opts, 也就是说最终会采用mapred.map.child.java.opts定义的jvm参数,如果有冲突的话。
reduce阶段:mapreduce.admin.reduce.child.java.opts < mapred.child.java.opts < mapred.reduce.child.java.opts
hadoop源码参考:org.apache.hadoop.mapred.MapReduceChildJVM.getChildJavaOpts方法。
2) Java heapspace
“Error: Java heapspace”异常信息,通常会伴随着143错误码,比如:
Task: attempt_1625727533919_10768_m_000157_3 - exited : Java heap spaceContainer exited with a non-zero exit code 143.
解决办法:增加内存
conf.set("mapreduce.map.memory.mb", "8192");
通用解决办法
目前MapReduce主要通过两个组参数去控制内存:(将如下参数调大)
Maper:
mapreduce.map.java.opts=-Xmx2048m(默认参数,表示jvm堆内存,注意是mapreduce不是mapred)
mapreduce.map.memory.mb=2304(container的内存)
Reducer:
mapreduce.reduce.java.opts=-=-Xmx2048m(默认参数,表示jvm堆内存)
mapreduce.reduce.memory.mb=2304(container的内存)
注意:因为在yarn container这种模式下,map/reduce task是运行在Container之中的,所以上面提到的mapreduce.map(reduce).memory.mb大小都大于mapreduce.map(reduce).java.opts值的大小。mapreduce.{map|reduce}.java.opts能够通过Xmx设置JVM最大的heap的使用,一般设置为0.75倍的memory.mb,因为需要为java code等预留些空间。
3) 虚拟内存 / 物理内存溢出
虚拟内存溢出:
Current usage: 1.1gb of 2.0gb physical memory used; 4.6gb of 4.2gb virtual memory used. Killing container.
这段错误信息告诉我们,物理内存没有用完,虚拟内存使用了4.6GB,而实际虚拟内存只有4.2GB。
- 方法一:提高
yarn.nodemanager.vmem-pmem-ratio = 5或者更高;【推荐】; - 方法二:yarn.nodemanager.vmem-check-enabled =false ;关闭虚拟内存检查;不推荐;
- 方法三:提高物理内存分配,相应的虚拟内存自然就多了,但是这样不是最优;
物理内存溢出:
Current usage: 2.1gb of 2.0gb physical memory used; 3.6gb of 4.2gb virtual memory used. Killing container.【即物理内存溢出】;
方法一:mapreduce.map.memory.mb = 3GB以上,然后测试这个map/reduce task需要使用多少内存才够用,提高这个值直到不报错为止。
方法二:提高yarn.scheduler.minimum-allocation-mb = 3GB以上,同理【不推荐】
- 栈内存溢出
抛出异常为:java.lang.StackOverflflowError,常会出现在SQL中(SQL语句中条件组合太多,被解析成为不断的递归调用),或MR代码中有递归调用。这种深度的递归调用在栈中方法调用链条太长导致的。出现这种错误一般说明程序写的有问题。
二、MRAppMaster内存不足
如果作业的输入的数据很大,导致产生了大量的Mapper和Reducer数量,致使MRAppMaster(当前作业的管理者)的压力很大,最终导致MRAppMaster内存不足,作业跑了一般出现了OOM信息
异常信息为:
Exception: java.lang.OutOfMemoryError thrown from theUncaughtExceptionHandler in thread
“Socket Reader #1 for port 30703
Halting due to Out Of Memory Error…
Halting due to Out Of Memory Error…
Halting due to Out Of Memory Error…
yarn.app.mapreduce.am.command-opts=-Xmx1024m(默认参数,表示jvm堆内存)
yarn.app.mapreduce.am.resource.mb=1536(container的内存)
三、非JVM内存溢出
异常信息一般为:java.lang.OutOfMemoryError:Direct buffffer memory
自己申请使用操作系统的内存,没有控制好,出现了内存泄露,导致的内存溢出。
四、其它参数
| 参数名称 | 默认值 | 描述 |
|---|---|---|
| yarn.scheduler.minimum-allocation-mb | 1024 | 每个container请求的最低jvm配置,单位m。如果请求的内存小于该值,那么会重新设置为该值。 |
| yarn.scheduler.maximum-allocation-mb | 8192 | 每个container请求的最高jvm配置,单位m。如果大于该值,会被重新设置。 |
| yarn.nodemanager.resource.memory-mb | 8192 | 每个nodemanager节点准备最高内存配置,单位m |
| yarn.nodemanager.vmem-pmem-ratio | 2.1 | 虚拟内存和物理内存之间的比率,如果提示virtual memory limits的时候,可以将该值调大。 |
| yarn.nodemanager.pmem-check-enabled | true | 是否进行物理内存限制比较,设置为false,不会进行大小的比较 |
| yarn.nodemanager.vmem-check-enabled | false | 是否进行虚拟内存限制比较。 |
| mapreduce.map.memory.mb | 1024 | map内存申请大小,单位m |
| mapreduce.reduce.memory.mb | 1024 | reduce内存申请大小,单位m |
| mapred.child.java.opts | -Xmx200 | map/reduce执行参数设置,可以参数Hadoop Mapreduce Error: GC overhead limit exceeded |
Yarn的ResourceManger(简称RM)通过逻辑上的队列分配内存,CPU等资源给application,默认情况下RM允许最大AM申请Container资源为8192MB(“yarn.scheduler.maximum-allocation-mb“),默认情况下的最小分配资源为1024M(“yarn.scheduler.minimum-allocation-mb“),AM只能以增量(”yarn.scheduler.minimum-allocation-mb“)和不会超过(“yarn.scheduler.maximum-allocationmb“)的值去向RM申请资源,AM负责将(“mapreduce.map.memory.mb“)和(“mapreduce.reduce.memory.mb“)的值规整到能被(“yarn.scheduler.minimum-allocation-mb“)整除,RM会拒绝申请内存超过8192MB和不能被1024MB整除的资源请求。(不同配置会有不同)
