天天看點

《Hadoop實戰第2版》——3.3節MapReduce任務的優化

3.3 mapreduce任務的優化

相信每個程式員在程式設計時都會問自己兩個問題“我如何完成這個任務”,以及“怎麼能讓程式運作得更快”。同樣,mapreduce計算模型的多次優化也是為了更好地解答這兩個問題。

mapreduce計算模型的優化涉及了方方面面的内容,但是主要集中在兩個方面:一是計算性能方面的優化;二是i/o操作方面的優化。這其中,又包含六個方面的内容。

任務排程

任務排程是hadoop中非常重要的一環,這個優化又涉及兩個方面的内容。計算方面:hadoop總會優先将任務配置設定給空閑的機器,使所有的任務能公平地分享系統資源。i/o方面:hadoop會盡量将map任務配置設定給inputsplit所在的機器,以減少網絡i/o的消耗。

資料預處理與inputsplit的大小

mapreduce任務擅長處理少量的大資料,而在處理大量的小資料時,mapreduce的性能就會遜色很多。是以在送出mapreduce任務前可以先對資料進行一次預處理,将資料合并以提高mapreduce任務的執行效率,這個辦法往往很有效。如果這還不行,可以參考map任務的運作時間,當一個map任務隻需要運作幾秒就可以結束時,就需要考慮是否應該給它配置設定更多的資料。通常而言,一個map任務的運作時間在一分鐘左右比較合适,可以通過設定map的輸入資料大小來調節map的運作時間。在fileinputformat中(除了combinefileinputformat),hadoop會在處理每個block後将其作為一個inputsplit,是以合理地設定block塊大小是很重要的調節方式。除此之外,也可以通過合理地設定map任務的數量來調節map任務的資料輸入。

map和reduce任務的數量

合理地設定map任務與reduce任務的數量對提高mapreduce任務的效率是非常重要的。預設的設定往往不能很好地展現出mapreduce任務的需求,不過,設定它們的數量也要有一定的實踐經驗。

首先要定義兩個概念—map/reduce任務槽。map/reduce任務槽就是這個叢集能夠同時運作的map/reduce任務的最大數量。比如,在一個具有1200台機器的叢集中,設定每台機器最多可以同時運作10個map任務,5個reduce任務。那麼這個叢集的map任務槽就是12000,reduce任務槽是6000。任務槽可以幫助對任務排程進行設定。

設定mapreduce任務的map數量主要參考的是map的運作時間,設定reduce任務的數量就隻需要參考任務槽的設定即可。一般來說,reduce任務的數量應該是reduce任務槽的0.95倍或是1.75倍,這是基于不同的考慮來決定的。當reduce任務的數量是任務槽的0.95倍時,如果一個reduce任務失敗,hadoop可以很快地找到一台空閑的機器重新執行這個任務。當reduce任務的數量是任務槽的1.75倍時,執行速度快的機器可以獲得更多的reduce任務,是以可以使負載更加均衡,以提高任務的處理速度。

combine函數

combine函數是用于本地合并資料的函數。在有些情況下,map函數産生的中間資料會有很多是重複的,比如在一個簡單的wordcount程式中,因為詞頻是接近與一個zipf分布的,每個map任務可能會産生成千上萬個記錄,若将這些記錄一一傳送給reduce任務是很耗時的。是以,mapreduce架構運作使用者寫的combine函數用于本地合并,這會大大減少網絡i/o操作的消耗。此時就可以利用combine函數先計算出在這個block中單詞the的個數。合理地設計combine函數會有效地減少網絡傳輸的資料量,提高mapreduce的效率。

在mapreduce程式中使用combine很簡單,隻需在程式中添加如下内容:

壓縮

編寫mapreduce程式時,可以選擇對map的輸出和最終的輸出結果進行壓縮(同時可以選擇壓縮方式)。在一些情況下,map的中間輸出可能會很大,對其進行壓縮可以有效地減少網絡上的資料傳輸量。對最終結果的壓縮雖然會減少資料寫hdfs的時間,但是也會對讀取産生一定的影響,是以要根據實際情況來選擇(第7章中提供了一個小實驗來驗證壓縮的效果)。

自定義comparator

在hadoop中,可以自定義資料類型以實作更複雜的目的,比如,當讀者想實作k-means算法(一個基礎的聚類算法)時可以定義k個整數的集合。自定義hadoop資料類型時,推薦自定義comparator來實作資料的二進制比較,這樣可以省去資料序列化和反序列化的時間,提高程式的運作效率(具體會在第7章中講解)。