1. 程式人生 > >Google MapReduce作業

Google MapReduce作業

本篇部落格為一位大學生公選課作業,第一次用部落格,如果有用的不對的地方請多多諒解

瞭解一下mapreduce必知概念

  1. 使用者程式首先呼叫的 MapReduce 庫將輸入檔案分成 M 個數據片度,每個資料片段的大小一般從16MB 到 64MB(可以通過可選的引數來控制每個資料片段的大小)。然後使用者程式在機群中建立大量的程式副本。
  2. 這些程式副本中的有一個特殊的程式–master。副本中其它的程式都是 worker 程式,由 master 分配任務。有 M 個 Map 任務和 R 個 Reduce 任務將被分配,master 將一個 Map 任務或 Reduce 任務分配給一個空閒的 worker。
  3. 被分配了 map 任務的 worker 程式讀取相關的輸入資料片段,從輸入的資料片段中解析出 key/value pair,然後把 key/value pair 傳遞給使用者自定義的 Map 函式,由 Map 數生成並輸出的中間 key/value pair,並快取在記憶體中。
  4. 快取中的 key/value pair 通過分割槽函式分成 R 個區域,之後週期性的寫入到本地磁碟上。快取的key/value pair 在本地磁碟上的儲存位置將被回傳給 master,由 master 負責把這些儲存位置再傳送給Reduce worker。
  5. 當 Reduce worker 程式接收到 master 程式發來的資料儲存位置資訊後,使用 RPC 從 Map worker 所在主機的磁碟上讀取這些快取資料。當 Reduce worker 讀取了所有的中資料後,通過對 key 進行排序後使得具有相同 key 值的資料聚合在一起。由於許多不同的key 值會對映到相同的 Reduce 任務上,因此必須進行排序。如果中間資料太大無法在記憶體。
  6. Reduce worker 程式遍歷排序後的中間資料,對於每一個唯一的中間 key 值,Reduce worker 程式將這個 key 值和它相關的中間 value 值的集合傳遞給使用者自定義的 Reduce 函式。Reduce 函式的輸出被追加到所屬分割槽的輸出檔案。
  7. 當所有的 Map 和 Reduce 任務都完成之後,master 喚醒使用者程式。在這個時候,在使用者程式裡的對MapReduce 呼叫才返回。
    <本處摘自google mapreduce論文>
    流程分析:

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函式。

故障處理

1 由於mapreduce庫使用成百上千的PC機組成的叢集來處理超大規模資料,所以處理機器故障成為了日常工作。就是說如果有一臺被分配了工作的機器故障了,master要怎麼處理這種事件:
master要有規律的週期性的ping每一個worker,如果worker沒有給master一個返回訊號,master就會認為這個worker死掉了,這樣master就會把分配給這臺機器的任務標記為空閒狀態,然後將這些空閒的任務分配給其他worker,其他worker只要再讀取這些任務執行就ok了,對於超大規模的叢集計算機來說,幾臺或者幾十臺機器失效都是無所謂的。
2 另一種故障就是master死了,如果出現這種情況,就終止mapreduce計算然後選舉一個其他的機器作為新的master

結語

MapReduce 程式設計模型在 Google 內部成功應用於多個領域。我們把這種成功歸結為幾個方面:首先,由於MapReduce 封裝了並行處理、容錯處理、資料本地化優化、負載均衡等等技術難點的細節,這使得 MapReduce庫易於使用。即便對於完全沒有並行或者分散式系統開發經驗的程式設計師而言;其次,大量不同型別的問可以通過 MapReduce 簡單的解決。比如,MapReduce 用於生成 Google 的網路搜尋服務所需要的資料、用來排序、用來資料探勘、用於機器學習,以及很多其它的系統;第三,我們實現了一個在數千臺計算機組成的大型叢集上靈活部署執行的 MapReduce。這個實現使得有效利用這些豐富的計算資源變得非常簡單,因適合用來解決 Google 遇到的其他很多需要大量計算的問題。
我們也從 MapReduce 開發過程中學到了不少東西。首先,約束程式設計模式使得並行和分散式計算非常容易,也易於構造容錯的計算環境;其次,網路頻寬是稀有資源。大量的系統優化是針對減少網路傳輸量為目的的:本地優化策略使大量的資料從本地磁碟讀取,中間檔案寫入本地磁碟、並且只寫一份中間檔案也節約了頻寬;第三,多次執行相同的任務可以減少效能緩慢的機器帶來的負面影響,同時解決了由於機器失效導致的資料丟失問題。