常常被一些用戶問到,說“為什么我的mapreduce作業總是運行到某個階段就報出如下錯誤,然后失敗呢?以前同一個作業沒出現過的呀?”
10/01/10 12:48:01 INFO mapred.JobClient: Task Id : attempt_201001061331_0002_m_000027_0, Status : FAILED
java.lang.OutOfMemoryError: Java heap space
at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.<init>(MapTask.java:498)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:305)
at org.apache.hadoop.mapred.Child.main(Child.java:158)
其實這樣的錯誤有時候並不是程序邏輯的問題(當然有可能是由於程序寫的不夠高效,產生的內存消耗不合理而導致),而是由於同樣的作業,在數據量和數據本身發生不同時就會占據不同數量的內存空間。由於hadoop的mapreduce作業的運行機制是:在jobtracker接到客戶端來的job提交后,將許多的task分配到集群中各個tasktracker上進行分塊的計算,而根據代碼中的邏輯可以看出,其實是在tasktracker上啟了一個java進程進行運算,進程中有特定的端口和網絡機制來保持map 和reduce之間的數據傳輸,所以,這些OOM的錯誤,其實就是這些java進程中報出了OOM的錯誤。
知道了原因以后就好辦了,hadoop的mapreduce作業啟動的時候,都會讀取jobConf中的配置(hadoop-site.xml),只要在該配置文件中將每個task的jvm進程中的-Xmx所配置的java進程的max heap size加大,就能解決這樣的問題:
<property>
<name>mapred.child.java.opts</name>
<value>-Xmx1024m</value>
</property>
PS:該選項默認是200M
新版本應該是在conf/hadoop-env.sh文件中修改。默認為1000M
通過此配置可以增加hadoop的jvm可分配的的內存大小。
對於通過RPM or DEB方式來安裝的,所有的配置文件在 /etc/hadoop目錄下, /etc/hadoop/hadoop-env.sh 里設置了java可用的最大堆內存大小:
|
1
|
export
HADOOP_CLIENT_OPTS=
"-Xmx128m $HADOOP_CLIENT_OPTS"
|
可以改變此設置為:
|
1
|
export
HADOOP_CLIENT_OPTS=
"-Xmx2048m $HADOOP_CLIENT_OPTS"
|
來增加可用內存大小。
