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= |
每個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>