1. 程式人生 > >hadoop學習(七)WordCount+Block+Split+Shuffle+Map+Reduce技術詳解

hadoop學習(七)WordCount+Block+Split+Shuffle+Map+Reduce技術詳解

       1、在map task執行時,它的輸入資料來源於HDFS的block,當然在MapReduce概念中,map task只讀取split。Split與block的對應關係在上面我們已經說的很明白了。在WordCount例子裡,假設map的輸入資料都是像 “aaa”這樣的字串。 
       2、在經過mapper的執行後,我們得知mapper的輸出是這樣一個key/value對: key是“aaa”, value是數值1。因為當前map端只做加1的操作,在reduce task裡才去合併結果集。前面我們知道這個job有3個reduce task,到底當前的“aaa”應該交由哪個reduce去做呢,是需要現在決定的。 
        MapReduce提供Partitioner介面,它的作用就是根據key或value及reduce的數量來決定當前的這對輸出資料最終應該交由哪個 reduce task處理。預設對key hash後再以reduce task數量取模。預設的取模方式只是為了平均reduce的處理能力,如果使用者自己對Partitioner有需求,可以訂製並設定到job上。 
       在上面的例子中,“aaa”經過Partitioner後返回0,也就是這對值應當交由第一個reducer來處理。接下來,需要將資料寫入記憶體緩衝區中,緩衝區的作用是批量收集map結果,減少磁碟IO的影響。我們的key/value對以及Partition的結果都會被寫入緩衝區。當然寫入之 前,key與value值都會被序列化成位元組陣列。 而整個記憶體緩衝區就是一個位元組陣列。
       3、這個記憶體緩衝區是有大小限制的,預設是100MB。當map task的輸出結果很多時,就可能會撐爆記憶體,所以需要在一定條件下將緩衝區中的資料臨時寫入磁碟,然後重新利用這塊緩衝區。這個從記憶體往磁碟寫資料的過程被稱為Spill,中文可譯為溢寫
這個溢寫是由單獨執行緒來完成,不影響往緩衝區寫map結果的執行緒。溢寫執行緒啟動時不應該阻止map 的結果輸出,所以整個緩衝區有個溢寫的比例spill.percent。這個比例預設是0.8,也就是當緩衝區的資料已經達到閾值(buffer size * spill percent = 100MB * 0.8 = 80MB),溢寫執行緒啟動,鎖定這80MB的記憶體,執行溢寫過程。Map task的輸出結果還可以往剩下的20MB記憶體中寫,互不影響。 
       當溢寫執行緒啟動後,需要對這80MB空間內的key做排序(Sort)。排序是MapReduce模型預設的行為,這裡的排序也是對序列化的位元組做的排序。
 
       在這裡我們可以想想,因為map task的輸出是需要傳送到不同的reduce端去,而記憶體緩衝區沒有對將傳送到相同reduce端的資料做合併,那麼這種合併應該是體現是磁碟檔案中的。從官方圖上也可以看到寫到磁碟中的溢寫檔案是對不同的reduce端的數值做過合併。所以溢寫過程一個很重要的細節在於,如果有很多個 key/value對需要傳送到某個reduce端去,那麼需要將這些key/value值拼接到一塊,減少與partition相關的索引記錄。 
       在針對每個reduce端而合併資料時,有些資料可能像這樣:“aaa”/1, “aaa”/1。對於Wordcount例子,就是簡單地統計單詞出現的次數,如果在同一個map task的結果中有很多個像“aaa”一樣出現多次的key,我們就應該把它們的值合併到一塊,這個過程叫reduce也叫combine。
但 MapReduce的術語中,reduce只指reduce端執行從多個map task取資料做計算的過程。除reduce外,非正式地合併資料只能算做combine了。其實大家知道的,MapReduce中將Combiner等 同於Reducer。 
       如果client設定過Combiner,那麼現在就是使用Combiner的時候了。將有相同key的key/value對的value加起來,減少溢寫到磁碟的資料量。Combiner會優化MapReduce的中間結果,所以它在整個模型中會多次使用。那哪些場景才能使用Combiner呢?從這裡分析,Combiner的輸出是Reducer的輸入,Combiner絕不能改變最終的計算結果。所以從我的想法來看,Combiner只應該用於那種 Reduce的輸入key/value與輸出key/value型別完全一致,且不影響最終結果的場景。比如累加,最大值等。Combiner的使用一定得慎重,如果用好,它對job執行效率有幫助,反之會影響reduce的最終結果。 
       4、每次溢寫會在磁碟上生成一個溢寫檔案,如果map的輸出結果真的很大,有多次這樣的溢寫發生,磁碟上相應的就會有多個溢寫檔案存在。當map task真正完成時,記憶體緩衝區中的資料也全部溢寫到磁碟中形成一個溢寫檔案。最終磁碟中會至少有一個這樣的溢寫檔案存在(如果map的輸出結果很少,當 map執行完成時,只會產生一個溢寫檔案),因為最終的檔案只有一個,所以需要將這些溢寫檔案歸併到一起,這個過程就叫做Merge。Merge是怎樣的?如前面的例子,“aaa”從某個map task讀取過來時值是5,從另外一個map 讀取時值是8,因為它們有相同的key,所以得merge成group。什麼是group。對於“aaa”就是像這樣的:{“aaa”, [5, 8, 2, …]},陣列中的值就是從不同溢寫檔案中讀取出來的,然後再把這些值加起來。請注意,因為merge是將多個溢寫檔案合併到一個檔案,所以可能也有相同的 key存在,在這個過程中如果client設定過Combiner,也會使用Combiner來合併相同的key。
       至此,map端的所有工作都已結束,最終生成的這個檔案也存放在TaskTracker夠得著的某個本地目錄內。每個reduce task不斷地通過RPC從JobTracker那裡獲取map task是否完成的資訊,如果reduce task得到通知,獲知某臺TaskTracker上的map task執行完成,Shuffle的後半段過程開始啟動。