1. 程式人生 > >Hadoop作業JVM堆大小設定優化

Hadoop作業JVM堆大小設定優化

Container is running beyond memory limitshttp://stackoverflow.com/questions/21005643/container-is-running-beyond-memory-limits`  

[hadoop] - Container [xxxx] is running beyond physical/virtual memory limits. http://www.cnblogs.com/liuming1992/p/5040262.html

當執行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

針對該異常資訊,有多種方式進行解決:

第一種:

  直接將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的一個大小值

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

mapred.child.java.opts:當需要處理超大資料(mapper大於10?)最好將值設定成-Xmx1024m或者更高(-Xmx2048m)才能避免出現“核心已轉儲”這種jvm記憶體溢位的錯誤!!

http://slaytanic.blog.51cto.com/2057708/1101360/

name value Description
hadoop.job.history.location job歷史檔案儲存路徑,無可配置引數,也不用寫在配置檔案裡,預設在logs的history資料夾下。
hadoop.job.history.user.location 使用者歷史檔案存放位置
io.sort.factor 30 這裡處理流合併時的檔案排序數,我理解為排序時開啟的檔案數
io.sort.mb 600 排序所使用的記憶體數量,單位兆,預設1,我記得是不能超過mapred.child.java.opt設定,否則會OOM
mapred.job.tracker hadoopmaster:9001 連線jobtrack伺服器的配置項,預設不寫是local,map數1,reduce數1
mapred.job.tracker.http.address 0.0.0.0:50030 jobtracker的tracker頁面服務監聽地址
mapred.job.tracker.handler.count 15 jobtracker服務的執行緒數
mapred.task.tracker.report.address 127.0.0.1:0 tasktracker監聽的伺服器,無需配置,且官方不建議自行修改
mapred.local.dir /data1/hdfs/mapred/local,
/data2/hdfs/mapred/local,
...
mapred做本地計算所使用的資料夾,可以配置多塊硬碟,逗號分隔
mapred.system.dir /data1/hdfs/mapred/system,
/data2/hdfs/mapred/system,
...
mapred存放控制檔案所使用的資料夾,可配置多塊硬碟,逗號分隔。
mapred.temp.dir /data1/hdfs/mapred/temp,
/data2/hdfs/mapred/temp,
...
mapred共享的臨時資料夾路徑,解釋同上。
mapred.local.dir.minspacestart 1073741824 本地運算資料夾剩餘空間低於該值則不在本地做計算。位元組配置,預設0
mapred.local.dir.minspacekill 1073741824 本地計算資料夾剩餘空間低於該值則不再申請新的任務,位元組數,預設0
mapred.tasktracker.expiry.interval 60000 TT在這個時間內沒有傳送心跳,則認為TT已經掛了。單位毫秒
mapred.map.tasks 2 預設每個job所使用的map數,意思是假設設定dfs塊大小為64M,需要排序一個60M的檔案,也會開啟2個map執行緒,當jobtracker設定為本地是不起作用。
mapred.reduce.tasks 1 解釋同上
mapred.jobtracker.restart.recover true | false 重啟時開啟任務恢復,預設false
mapred.jobtracker.taskScheduler org.apache.hadoop.mapred.
CapacityTaskScheduler

org.apache.hadoop.mapred.
JobQueueTaskScheduler

org.apache.hadoop.mapred.
FairScheduler
重要的東西,開啟工作管理員,不設定的話,hadoop預設是FIFO排程器,其他可以使用公平和計算能力排程器
mapred.reduce.parallel.copies 10 reduce在shuffle階段使用的並行複製數,預設5
mapred.child.java.opts

-Xmx2048m

-Djava.library.path=
/opt/hadoopgpl/native/
Linux-amd64-64

每個TT子程序所使用的虛擬機器記憶體大小
tasktracker.http.threads 50 TT用來跟蹤task任務的http server的執行緒數
mapred.task.tracker.http.address 0.0.0.0:50060 TT預設監聽的httpIP和埠,預設可以不寫。埠寫0則隨機使用。
mapred.output.compress true | false 任務結果採用壓縮輸出,預設false,建議false
mapred.output.compression.codec org.apache.hadoop.io.
compress.DefaultCodec
輸出結果所使用的編解碼器,也可以用gz或者bzip2或者lzo或者snappy等
mapred.compress.map.output true | false map輸出結果在進行網路交換前是否以壓縮格式輸出,預設false,建議true,可以減小頻寬佔用,代價是會慢一些。
mapred.map.output.compression.codec com.hadoop.compression.
lzo.LzoCodec
map階段壓縮輸出所使用的編解碼器
map.sort.class org.apache.hadoop.util.
QuickSort
map輸出排序所使用的演算法,預設快排。
mapred.hosts conf/mhost.allow 允許連線JT的TT伺服器列表,空值全部允許
mapred.hosts.exclude conf/mhost.deny 禁止連線JT的TT列表,節點摘除是很有作用。
mapred.queue.names ETL,rush,default 配合排程器使用的佇列名列表,逗號分隔
mapred.tasktracker.map.
tasks.maximum
12 每伺服器允許啟動的最大map槽位數。
mapred.tasktracker.reduce.
tasks.maximum
6 每伺服器允許啟動的最大reduce槽位數

http://blog.csdn.net/lalaguozhe/article/details/9076895

​前一陣子發現使用者提交的Hive query和Hadoop job會導致叢集的load非常高,經檢視配置,發現很多使用者擅自將mapred.child.Java.opts設定的非常大,比如-Xmx4096m(我們預設設定是-Xmx1024m),  導致了tasktracker上記憶體資源耗盡,進而開始不斷swap磁碟上資料,load飆升

TaskTracker在spawn一個map/reduce task jvm的時候,會根據使用者JobConf裡面的值設定jvm的引數,然後寫入一個taskjvm.sh檔案中,然後呼叫Linux命令"bin/bash -c taskjvm.sh"來執行task,

mapred.child.java.opts就是設定jvm的引數之一,在新版本中已經標註Deprecateded,取而代之的是區分Map task和Reduce task的jvm opts,mapred.map.child.java.opts和mapred.reduce.child.java.opts(預設值為-Xmx200m)

當用戶在不設該值情況下,會以最大1G jvm heap size啟動task,有可能導致OutOfMemory,所以最簡單的做法就是設大引數,並且由於這個值不是final,所以使用者在自己的mapred-site.xml中可以覆蓋預設值。但是如果很多使用者都無限度設定的話,high load問題就來了。

其實在構造JVM Args的過程中,是有另外一個admin引數可以覆蓋使用者端設定的mapreduce.admin.map.child.java.opts, mapreduce.admin.reduce.child.java.opts

經測試,如果相同的jvm arg如果寫在後面,比如"-Xmx4000m -Xmx1000m",後面的會覆蓋前面的,“-Xmx1000m”會最終生效,通過這種方式,我們就可以有限度的控制heap size了

終在mapred-site.xml中加上

<property>
      <name>mapreduce.admin.map.child.java.opts</name>
      <value>-Xmx1024m</value>
</property>
<property>
      <name>mapreduce.admin.reduce.child.java.opts</name>
      <value>-Xmx1536m</value>
</property>