hadoop 配置項的調優(R1)
dfs.block.size
決定HDFS檔案block數量的多少(檔案個數),它會間接的影響Job Tracker的排程和記憶體的佔用(更影響記憶體的使用),
mapred.map.tasks.speculative.execution=true
mapred.reduce.tasks.speculative.execution=true
這是兩個推測式執行的配置項,預設是true
所謂的推測執行,就是當所有task都開始執行之後,Job Tracker會統計所有任務的平均進度,如果某個task所在的task node機器配
置比較低或者CPU load很高(原因很多),導致任務執行比總體任務的平均執行要慢,此時Job Tracker會啟動一個新的任務
(duplicate task),原有任務和新任務哪個先執行完就把另外一個kill掉,這也是我們經常在Job Tracker頁面看到任務執行成功,但
是總有些任務被kill,就是這個原因。
mapred.child.java.opts
一般來說,都是reduce耗費記憶體比較大,這個選項是用來設定JVM堆的最大可用記憶體,但不要設定過大,如果超過2G(這是數字有
待考證),就應該考慮一下最佳化程式。
Input Split的大小,決定了一個Job擁有多少個map,預設64M每個Split,如果輸入的資料量巨大,那麼預設的64M的block會有特
別多Map Task,叢集的網路傳輸會很大,給Job Tracker的排程、佇列、記憶體都會帶來很大壓力。
mapred.min.split.size
這個配置決定了每個Input Split 的最小值,也間接決定了一個job的map數量
HDFS塊大小是在job寫入時決定的,而分片的大小,是由三個元素決定的(在3各種去最大的那個)
(1) 輸入的塊數 (2) Mapred.min.split.size (3) Job.setNumMapTasks()
mapred.compress.map.output
壓縮Map的輸出,這樣做有兩個好處:
a)壓縮是在記憶體中進行,所以寫入map本地磁碟的資料就會變小,大大減少了本地IO次數
b) Reduce從每個map節點copy資料,也會明顯降低網路傳輸的時間
注:資料序列化其實效果會更好,無論是磁碟IO還是資料大小,都會明顯的降低。
io.sort.mb
以MB為單位,預設100M,這個值比較小
map節點沒執行完時,記憶體的資料過多,要將記憶體中的內容寫入洗盤,這個設定就是設定記憶體緩衝的大小,在suffle之前
這個選項定義了map輸出結果在記憶體裡佔用buffer的大小,當buffer達到某個閾值(後面那條配置),會啟動一個後臺執行緒來對buffer
的內容進行排序,然後寫入本地磁碟(一個spill檔案)
根據map輸出資料量的大小,可以適當的調整buffer的大小,注意是適當的調整,並不是越大越好,假設記憶體無限大,
io.sort.mb=1024(1G), 和io.sort.mb=300 (300M),前者未必比後者快:
(1)1G的資料排序一次
(2)排序3次,每次300MB
一定是後者快(歸併排序)
io.sort.spill.percent
這個值就是上面提到的buffer的閾值,預設是0.8,既80%,當buffer中的資料達到這個閾值,後臺執行緒會起來對buffer中已有的數
據進行排序,然後寫入磁碟,此時map輸出的資料繼續往剩餘的20% buffer寫資料,如果buffer的剩餘20%寫滿,排序還沒結束,
map task被block等待。
如果你確認map輸出的資料基本有序,排序時間很短,可以將這個閾值適當調高,更理想的,如果你的map輸出是有序的資料,那
麼可以把buffer設的更大,閾值設定為1.
Io.sort.factor
同時開啟的檔案控制程式碼的數量,預設是10
當一個map task執行完之後,本地磁碟上(mapred.local.dir)有若干個spill檔案,map task最後做的一件事就是執行merge sort,
把這些spill檔案合成一個檔案(partition,combine階段)。
執行merge sort的時候,每次同時開啟多少個spill檔案,就是由io.sort.factor決定的。開啟的檔案越多,不一定merge sort就越
快,也要根據資料情況適當的調整。
注:merge排序的結果是兩個檔案,一個是index,另一個是資料檔案,index檔案記錄了每個不同的key在資料檔案中的偏移量(即partition)。
在map節點上,如果發現map所在的子節點的機器io比較重,原因可能是io.sort.factor這個設定的比較小,io.sort.factor設定小的
話,如果spill檔案比較多,merge成一個檔案要很多輪讀取操作,這樣就提升了io的負載。io.sort.mb小了,也會增加io的負載。
如果設定了執行combine的話,combine只是在merge的時候,增加了一步操作,不會改變merge的流程,所以combine不會減少
或者增加檔案個數。另外有個min.num.spills.for.combine的引數,表示執行一個merge操作時,如果輸入檔案數小於這個數字,就
不呼叫combiner。如果設定了combiner,在寫spill檔案的時候也會呼叫,這樣加上merge時候的呼叫,就會執行兩次combine。
提高Reduce的執行效率,除了在Hadoop框架方面的最佳化,重點還是在程式碼邏輯上的最佳化.比如:對Reduce接受到的value可能有重
復的,此時如果用Java的Set或者STL的Set來達到去重的目的,那麼這個程式不是擴充套件良好的(non-scalable),受到資料量的限制,
當資料膨脹,記憶體勢必會溢位
mapred.reduce.parallel.copies
Reduce copy資料的執行緒數量,預設值是5
Reduce到每個完成的Map Task 複製資料(透過RPC呼叫),預設同時啟動5個執行緒到map節點取資料。這個配置還是很關鍵的,
如果你的map輸出資料很大,有時候會發現map早就100%了,reduce卻在緩慢的變化,那就是copy資料太慢了,比如5個執行緒
copy 10G的資料,確實會很慢,這時就要調整這個引數,但是調整的太大,容易造成叢集擁堵,所以 Job tuning的同時,也是個權
衡的過程,要熟悉所用的資料!
mapred.job.shuffle.input.buffer.percent
當指定了JVM的堆記憶體最大值以後,上面這個配置項就是Reduce用來存放從Map節點取過來的資料所用的記憶體佔堆記憶體的比例,默
認是0.7,既70%,通常這個比例是夠了,但是對於大資料的情況,這個比例還是小了一些,0.8-0.9之間比較合適。(前提是你的
reduce函式不會瘋狂的吃掉記憶體)
mapred.job.shuffle.merge.percent(預設值0.66)
mapred.inmem.merge.threshold(預設值1000)
第一個指的是從Map節點取資料過來,放到記憶體,當達到這個閾值之後,後臺啟動執行緒(通常是Linux native process)把記憶體中的
資料merge sort,寫到reduce節點的本地磁碟;
第二個指的是從map節點取過來的檔案個數,當達到這個個數之後,也進行merger sort,然後寫到reduce節點的本地磁碟;這兩
個配置項第一個優先判斷,其次才判斷第二個thresh-hold。
從實際經驗來看,mapred.job.shuffle.merge.percent預設值偏小,完全可以設定到0.8左右;第二個預設值1000,完全取決於
map輸出資料的大小,如果map輸出的資料很大,預設值1000反倒不好,應該小一些,如果map輸出的資料不大(light
weight),可以設定2000或者以上。
mapred.reduce.slowstart.completed.maps (map完成多少百分比時,開始shuffle)
當map執行慢,reduce執行很快時,如果不設定mapred.reduce.slowstart.completed.maps會使job的shuffle時間變的很長,
map執行完很早就開始了reduce,導致reduce的slot一直處於被佔用狀態。mapred.reduce.slowstart.completed.maps 這個值是
和“執行完的map數除以總map數”做判斷的,當後者大於等於設定的值時,開始reduce的shuffle。所以當map比reduce的執行
時間多很多時,可以調整這個值(0.75,0.80,0.85及以上)
下面從流程裡描述一下各個引數的作用:
當map task開始運算,併產生中間資料時,其產生的中間結果並非直接就簡單的寫入磁碟。這中間的過程比較複雜,並且利用到了
記憶體buffer來進行已經產生的部分結果的快取,並在記憶體buffer中進行一些預排序來最佳化整個map的效能。每一個map都會對應存
在一個記憶體buffer(MapOutputBuffer),map會將已經產生的部分結果先寫入到該buffer中,這個buffer預設是100MB大小,但
是這個大小是可以根據job提交時的引數設定來調整的,該引數即為:io.sort.mb。當map的產生資料非常大時,並且把io.sort.mb
調大,那麼map在整個計算過程中spill的次數就勢必會降低,map task對磁碟的操作就會變少,如果map tasks的瓶頸在磁碟上,
這樣調整就會大大提高map的計算效能。
map在執行過程中,不停的向該buffer中寫入已有的計算結果,但是該buffer並不一定能將全部的map輸出快取下來,當map輸出
超出一定閾值(比如100M),那麼map就必須將該buffer中的資料寫入到磁碟中去,這個過程在mapreduce中叫做spill。map並
不是要等到將該buffer全部寫滿時才進行spill,因為如果全部寫滿了再去寫spill,勢必會造成map的計算部分等待buffer釋放空間的
情況。所以,map其實是當buffer被寫滿到一定程度(比如80%)時,就開始進行spill。這個閾值也是由一個job的配置引數來控
制,即io.sort.spill.percent,預設為0.80或80%。這個引數同樣也是影響spill頻繁程度,進而影響map task執行週期對磁碟的讀寫
頻率的。但非特殊情況下,通常不需要人為的調整。調整io.sort.mb對使用者來說更加方便。
當map task的計算部分全部完成後,如果map有輸出,就會生成一個或者多個spill檔案,這些檔案就是map的輸出結果。map在正
常退出之前,需要將這些spill合併(merge)成一個,所以map在結束之前還有一個merge的過程。merge的過程中,有一個引數
可以調整這個過程的行為,該引數為:io.sort.factor。該引數預設為10。它表示當merge spill檔案時,最多能有多少並行的stream
向merge檔案中寫入。比如如果map產生的資料非常的大,產生的spill檔案大於10,而io.sort.factor使用的是預設的10,那麼當
map計算完成做merge時,就沒有辦法一次將所有的spill檔案merge成一個,而是會分多次,每次最多10個stream。這也就是說,
當map的中間結果非常大,調大io.sort.factor,有利於減少merge次數,進而減少map對磁碟的讀寫頻率,有可能達到最佳化作業的
目的。
當job指定了combiner的時候,我們都知道map介紹後會在map端根據combiner定義的函式將map結果進行合併。執行combiner
函式的時機有可能會是merge完成之前,或者之後,這個時機可以由一個引數控制,即min.num.spill.for.combine(default 3),
當job中設定了combiner,並且spill數最少有3個的時候,那麼combiner函式就會在merge產生結果檔案之前執行。透過這樣的方
式,就可以在spill非常多需要merge,並且很多資料需要做conbine的時候,減少寫入到磁碟檔案的資料數量,同樣是為了減少對磁
盤的讀寫頻率,有可能達到最佳化作業的目的。
減少中間結果讀寫進出磁碟的方法不止這些,還有就是壓縮。也就是說map的中間,無論是spill的時候,還是最後merge產生的結
果檔案,都是可以壓縮的。壓縮的好處在於,透過壓縮減少寫入讀出磁碟的資料量。對中間結果非常大,磁碟速度成為map執行瓶
頸的job,尤其有用。控制map中間結果是否使用壓縮的引數為:mapred.compress.map.output(true/false)。將這個引數設定為
true時,那麼map在寫中間結果時,就會將資料壓縮後再寫入磁碟,讀結果時也會採用先解壓後讀取資料。這樣做的後果就是:寫
入磁碟的中間結果資料量會變少,但是cpu會消耗一些用來壓縮和解壓。所以這種方式通常適合job中間結果非常大,瓶頸不在
cpu,而是在磁碟的讀寫的情況。說的直白一些就是用cpu換IO。根據觀察,通常大部分的作業cpu都不是瓶頸,除非運算邏輯異常
複雜。所以對中間結果採用壓縮通常來說是有收益的。
當採用map中間結果壓縮的情況下,使用者還可以選擇壓縮時採用哪種壓縮格式進行壓縮,現在hadoop支援的壓縮格式有:
GzipCodec,LzoCodec,BZip2Codec,LzmaCodec等壓縮格式。通常來說,想要達到比較平衡的cpu和磁碟壓縮比,LzoCodec
比較適合。但也要取決於job的具體情況。使用者若想要自行選擇中間結果的壓縮演算法,可以設定配置引數:
mapred.map.output.compression.codec=org.apache.hadoop.io.compress.DefaultCodec或者其他使用者自行選擇的壓縮方式。
轉載地址:http://blog.sina.com.cn/s/blog_6a67b5c50100vop9.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26613085/viewspace-1098694/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- hadoop 調優1Hadoop
- 關於Hadoop調優Hadoop
- Hadoop引數調優Hadoop
- Hadoop-調優剖析Hadoop
- FreeBSD下安裝配置Hadoop叢集(效能調優)Hadoop
- hadoop之 引數調優Hadoop
- Hadoop是怎麼分塊的(R1)Hadoop
- Hadoop中一個distcp (R1)HadoopTCP
- Hadoop作業調優引數Hadoop
- JVM 調優示例和配置JVM
- mysql的配置檔案(調優之後)MySql
- Spark面試題(八)——Spark的Shuffle配置調優Spark面試題
- YARN的Memory和CPU調優配置詳解Yarn
- 史上最深入解析hadoop調優,沒有之一!Hadoop
- 分析從管理員角度對Hadoop進行調優Hadoop
- 新安裝的MySQL必須調整的10項配置MySql
- 堅果R1配置效能全面評測 堅果R1值得買嗎?
- 【進階之路】執行緒池配置與調優的一些高階選項(一)執行緒
- hive查詢注意事項和調優Hive
- Spark效能調優——9項基本原則Spark
- SAP下的ORACLE安裝後的幾個調優項Oracle
- hadoop叢集搭建配置檔案優化引數Hadoop優化
- 安裝MySQL後,需要調整的10個效能配置項MySql
- 安裝完 MySQL 後必須調整的 10 項配置MySql
- 安裝完MySQL後必須調整的10項配置MySql
- 【Spark篇】---Spark調優之程式碼調優,資料本地化調優,記憶體調優,SparkShuffle調優,Executor的堆外記憶體調優Spark記憶體
- hadoop queue的配額調整Hadoop
- JVM調優總結-典型配置舉例1JVM
- JVM調優總結-典型配置舉例2JVM
- tomcat配置調優與安全總結(轉)Tomcat
- hadoop:spark-project專案的hadoop配置HadoopSparkProject
- Hadoop2.7實戰v1.0之JVM引數調優HadoopJVM
- hadoop 部署配置Hadoop
- cygwin 配置hadoopHadoop
- JVM調優總結(七)-典型配置舉例1JVM
- JVM調優總結(八)-典型配置舉例2JVM
- ArkTS 中的記憶體調優與配置:最佳實踐記憶體
- 【調優篇基本原理】優化器相關引數配置優化