1. 程式人生 > >大資料面試部分:MapReduce的工作原理

大資料面試部分:MapReduce的工作原理

3.講述一下mapreduce的流程(shuffle的sort,partitions,group)

首先是 Mapreduce經過SplitInput 輸入分片 決定map的個數在用Record記錄 key value。然後分為以下三個流程:

Map:

輸入  key(long型別偏移量)  value(Text一行字串)

輸出  key value

Shuffle:、

   合併(merge)map輸出時先輸出到環形記憶體,當記憶體使用率達到60%時開始溢位寫入到檔案,溢位檔案都是小檔案,所以就要合併他們,在這個構成中就會排序,根據key值比較排序

   排序(sort)如果你自定義了key的資料型別要求你的類一定是WriteableCompartor的子類,不想繼承WriteableCompartor,至少實現Writeable,這時你就必須在job上設定排序比較器job.setSortCmpartorClass(MyCompartor.class);而MyCompartor.class必須繼承RawCompartor的類或子類

   分割槽(partition)會根據map輸出的結果分成幾個檔案為reduce準備,有幾個reducetask就分成幾個檔案,在job上設定分割槽器job.setPartitionerClass(MyPartition.class)Myrtition.class要繼承Partitioner這個類

   分組(group)分割槽時會呼叫分組器,把同一分割槽中的相同key的資料對應的value製作成一個iterable,並且會在sort。在job上設定分組器。Job.setGroupCompartorClass(MyGroup.class)MyGroup.class必須繼承RawCompartor的類跟子類

上面的結果儲存到本地檔案中,而不是hdfs上

上面只要有完成結果,reduce就開始複製上面的結果,通過http方式

Reduce

  輸入key時map輸出時的key value是分組器分的iterable

  輸出 key value

  輸出結果儲存在hdfs上而不是本地檔案中

 MapReduce的執行步驟:

1、Map任務處理

1.1 讀取HDFS中的檔案。每一行解析成一個<k,v>。每一個鍵值對呼叫一次map函式。                <0,hello you>   <10,hello me>

1.2 覆蓋map(),接收1.1產生的<k,v>,進行處理,轉換為新的<k,v>輸出。          

<hello,1> <you,1> <hello,1> <me,1>

1.3 對1.2輸出的<k,v>進行分割槽。預設分為一個區。詳見《Partitioner

1.4 對不同分割槽中的資料進行排序(按照k)、分組。分組指的是相同key的value放到一個集合中。 排序後:<hello,1> <hello,1> <me,1> <you,1>  分組後:<hello,{1,1}><me,{1}><you,{1}>

1.5 (可選)對分組後的資料進行歸約。詳見《Combiner

2、Reduce任務處理

2.1 多個map任務的輸出,按照不同的分割槽,通過網路copy到不同的reduce節點上。(shuffle)詳見《shuffle過程分析

2.2 對多個map的輸出進行合併、排序。覆蓋reduce函式,接收的是分組後的資料,實現自己的業務邏輯, <hello,2> <me,1> <you,1>

    處理後,產生新的<k,v>輸出。

2.3 對reduce輸出的<k,v>寫到HDFS中。

1.MapReduce作業執行流程
2.Map、Reduce任務中Shuffle和排序的過程 

正文: 

1.MapReduce作業執行流程


下面貼出我用visio2010畫出的流程示意圖:

流程分析:


1.在客戶端啟動一個作業。


2.向JobTracker請求一個Job ID。


3.將執行作業所需要的資原始檔複製到HDFS上,包括MapReduce程式打包的JAR檔案、配置檔案和客戶端計算所得的輸入劃分資訊。這些檔案都存放在JobTracker專門為該作業建立的資料夾中。資料夾名為該作業的Job ID。JAR檔案預設會有10個副本(mapred.submit.replication屬性控制);輸入劃分資訊告訴了JobTracker應該為這個作業啟動多少個map任務等資訊。


4.JobTracker接收到作業後,將其放在一個作業佇列裡,等待作業排程器對其進行排程(這裡是不是很像微機中的程序排程呢,呵呵),當作業排程器根據自己的排程演算法排程到該作業時,會根據輸入劃分資訊為每個劃分建立一個map任務,並將map任務分配給TaskTracker執行。對於map和reduce任務,TaskTracker根據主機核的數量和記憶體的大小有固定數量的map槽和reduce槽。這裡需要強調的是:map任務不是隨隨便便地分配給某個TaskTracker的,這裡有個概念叫:資料本地化(Data-Local)。意思是:將map任務分配給含有該map處理的資料塊的TaskTracker上,同時將程式JAR包複製到該TaskTracker上來執行,這叫“運算移動,資料不移動”。而分配reduce任務時並不考慮資料本地化。


5.TaskTracker每隔一段時間會給JobTracker傳送一個心跳,告訴JobTracker它依然在執行,同時心跳中還攜帶著很多的資訊,比如當前map任務完成的進度等資訊。當JobTracker收到作業的最後一個任務完成資訊時,便把該作業設定成“成功”。當JobClient查詢狀態時,它將得知任務已完成,便顯示一條訊息給使用者。

以上是在客戶端、JobTracker、TaskTracker的層次來分析MapReduce的工作原理的,下面我們再細緻一點,從map任務和reduce任務的層次來分析分析吧。

2.Map、Reduce任務中Shuffle和排序的過程


同樣貼出我在visio中畫出的流程示意圖:

流程分析:

Map端:

1.每個輸入分片會讓一個map任務來處理,預設情況下,以HDFS的一個塊的大小(預設為64M)為一個分片,當然我們也可以設定塊的大小。map輸出的結果會暫且放在一個環形記憶體緩衝區中(該緩衝區的大小預設為100M,由io.sort.mb屬性控制),當該緩衝區快要溢位時(預設為緩衝區大小的80%,由io.sort.spill.percent屬性控制),會在本地檔案系統中建立一個溢位檔案,將該緩衝區中的資料寫入這個檔案。

2.在寫入磁碟之前,執行緒首先根據reduce任務的數目將資料劃分為相同數目的分割槽,也就是一個reduce任務對應一個分割槽的資料。這樣做是為了避免有些reduce任務分配到大量資料,而有些reduce任務卻分到很少資料,甚至沒有分到資料的尷尬局面。其實分割槽就是對資料進行hash的過程。然後對每個分割槽中的資料進行排序,如果此時設定了Combiner,將排序後的結果進行Combia操作,這樣做的目的是讓儘可能少的資料寫入到磁碟。

3.當map任務輸出最後一個記錄時,可能會有很多的溢位檔案,這時需要將這些檔案合併。合併的過程中會不斷地進行排序和combia操作,目的有兩個:1.儘量減少每次寫入磁碟的資料量;2.儘量減少下一複製階段網路傳輸的資料量。最後合併成了一個已分割槽且已排序的檔案。為了減少網路傳輸的資料量,這裡可以將資料壓縮,只要將mapred.compress.map.out設定為true就可以了。

4.將分割槽中的資料拷貝給相對應的reduce任務。有人可能會問:分割槽中的資料怎麼知道它對應的reduce是哪個呢?其實map任務一直和其父TaskTracker保持聯絡,而TaskTracker又一直和JobTracker保持心跳。所以JobTracker中儲存了整個叢集中的巨集觀資訊。只要reduce任務向JobTracker獲取對應的map輸出位置就ok了哦。

到這裡,map端就分析完了。那到底什麼是Shuffle呢?Shuffle的中文意思是“洗牌”,如果我們這樣看:一個map產生的資料,結果通過hash過程分割槽卻分配給了不同的reduce任務,是不是一個對資料洗牌的過程呢?呵呵。

Reduce端:

1.Reduce會接收到不同map任務傳來的資料,並且每個map傳來的資料都是有序的。如果reduce端接受的資料量相當小,則直接儲存在記憶體中(緩衝區大小由mapred.job.shuffle.input.buffer.percent屬性控制,表示用作此用途的堆空間的百分比),如果資料量超過了該緩衝區大小的一定比例(由mapred.job.shuffle.merge.percent決定),則對資料合併後溢寫到磁碟中。

2.隨著溢寫檔案的增多,後臺執行緒會將它們合併成一個更大的有序的檔案,這樣做是為了給後面的合併節省時間。其實不管在map端還是reduce端,MapReduce都是反覆地執行排序,合併操作,現在終於明白了有些人為什麼會說:排序是hadoop的靈魂。

3.合併的過程中會產生許多的中間檔案(寫入磁碟了),但MapReduce會讓寫入磁碟的資料儘可能地少,並且最後一次合併的結果並沒有寫入磁碟,而是直接輸入到reduce函式。

 

https://blog.csdn.net/tanggao1314/article/details/51275812(此部落格總結的挺好)