这几天于遇到一个略诡异的CASE:线上报警一个MR Job的一个MAP TASK使用的物理内存过大,仔细一看超过了Xmx=1.3GB,而物理内存消耗到1.7GB,第一反应是不是遇到JVM内存泄露了.先对MAP TASK做个dump分析:

MAP TASK内存泄露_第1张图片

发现实际JVM使用不到300MB,算上PermMaxPermSize=128MB),那其余的1.XGB的内存是哪里来的呢?想到了non-heap memoryleak,常见的主要几种:JNINIO,ZIPAWT,查看MAP日志发现处理大量的GZIP文件是不是可能由于这个导致的呢,由于MAP启动具有一定的随机性,常见的non-heap 分析工具可能比较困难,不过先Google了一下果然有所发现:http://code.google.com/p/bigstreams/issues/detail?id=30

Hadoop native gzip存在内存泄露!解决的办法就是用Javabuiltin GZIP或者其他压缩格式.线上是并用GZIPSNAPPY的,历史的GZIP还没有转到SNAPPY,看来有活干了...BTW,对于Sqoop的导入Job默认是gzip的,可以通过

--compression-codec org.apache.hadoop.io.compress.SnappyCodec来改变,同时最好结合--as-sequencefile




另外一个问题就是线上的内存使用率太低,因为io.sort.mb设置了256MB,怪不得JVM的old generation(主要就是mapoutput buffer)只用到了25%左右...因此这里的引出另外一个best practise是将io.sort.mb设置接近Xmx


最后,针对内存限制在HADOOP-0.20.0/1分别提出了几个参数来限制TASK的虚拟内存和物理内存的大小:HADOOP-5883:https://issues.apache.org/jira/browse/HADOOP-5883,MAPREDUCE-1221:https://issues.apache.org/jira/browse/HADOOP-5883 .


Have fun.