當運行mapreduce的時候,有時候會出現異常信息,提示物理內存或者虛擬內存超出限制,默認情況下:虛擬內存是物理內存的2.1倍。異常信息類似如下:
Container [pid=13026,containerID=container_1449820132317_0013_01_000012] is running beyond physical memory limits. Current usage: 1.0 GB of 1 GB physical memory used; 1.7 GB of 2.1 GB virtual memory used. Killing container. Dump of the process-tree for container_1449820132317_0013_01_000012 : |- PID PPID PGRPID SESSID CMD_NAME USER_MODE_TIME(MILLIS) SYSTEM_TIME(MILLIS) VMEM_USAGE(BYTES) RSSMEM_USAGE(PAGES) FULL_CMD_LINE |- 13044 13026 13026 13026 (java) 4479 494 1696595968 271631 /home/hadoop/cdh5.2.4/jdk1.7.0_79/bin/java -Djava.net.preferIPv4Stack=true -xxx
我們可以看到該異常信息是提示物理內存超過限制,但是通過我們查看代碼我們發現我們最終使用的內存沒有達到1G,只有500M-。(具體原因沒有細查)最終我們發現影響這個代碼執行的參數分別是:
參數 | 默認值 | 描述 |
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.nodemanager.pmem-check-enabled和yarn.nodemanager.vmem-check-enabled設置為false,那么可以杜絕異常信息的產生。
第二種:
如果異常信息提示的是virtual memory不夠,那么可以將yarn.nodemanager.vmem-pmem-ratio參數改大,那么也可以避免異常信息的產生。
第三種:
修改mapreduce參數,設置修改如下:
mapreduce.map.memory.mb = (1~2倍) * yarn.scheduler.minimum-allocation-mb
mapreduce.reduce.memory.mb = (1~4倍) * yarn.scheduler.minimum-allocation-mb
1. mapred.child.java.opts = -XmxTm(T數字要小於map和reduce的設置value)
2. mapreduce.map.java.opts=-Xmx(<mapreduce.map.memory.mb)m
mapreduce.reduce.java.opts=-Xmx(<mapreduce.reduce.memory.mb)m
總結:最終運行參數給定的jvm堆大小必須小於參數指定的map和reduce的memory大小,最好為70%以下。
hadoop源碼涉及到地方:
1. org.apache.hadoop.mapred.MapReduceChildJVM.getChildJavaOpts
2. org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl.MonitoringThread.run()<398-465行>(進行內存限制判斷)
3. org.apache.hadoop.yarn.server.nodemanager.containermanager.container.ContainerImpl.LaunchTransition.transition()<647-658行>(進行物理內存和虛擬內存大小限制計算和賦值)
物理內存大小其實就是mapreduce.map.memory.mb和mapreduce.reduce.memory.mb的一個大小值