Google MapReduce作業
本篇部落格為一位大學生公選課作業,第一次用部落格,如果有用的不對的地方請多多諒解
瞭解一下mapreduce必知概念
- 使用者程式首先呼叫的 MapReduce 庫將輸入檔案分成 M 個數據片度,每個資料片段的大小一般從16MB 到 64MB(可以通過可選的引數來控制每個資料片段的大小)。然後使用者程式在機群中建立大量的程式副本。
- 這些程式副本中的有一個特殊的程式–master。副本中其它的程式都是 worker 程式,由 master 分配任務。有 M 個 Map 任務和 R 個 Reduce 任務將被分配,master 將一個 Map 任務或 Reduce 任務分配給一個空閒的 worker。
- 被分配了 map 任務的 worker 程式讀取相關的輸入資料片段,從輸入的資料片段中解析出 key/value pair,然後把 key/value pair 傳遞給使用者自定義的 Map 函式,由 Map 數生成並輸出的中間 key/value pair,並快取在記憶體中。
- 快取中的 key/value pair 通過分割槽函式分成 R 個區域,之後週期性的寫入到本地磁碟上。快取的key/value pair 在本地磁碟上的儲存位置將被回傳給 master,由 master 負責把這些儲存位置再傳送給Reduce worker。
- 當 Reduce worker 程式接收到 master 程式發來的資料儲存位置資訊後,使用 RPC 從 Map worker 所在主機的磁碟上讀取這些快取資料。當 Reduce worker 讀取了所有的中資料後,通過對 key 進行排序後使得具有相同 key 值的資料聚合在一起。由於許多不同的key 值會對映到相同的 Reduce 任務上,因此必須進行排序。如果中間資料太大無法在記憶體。
- Reduce worker 程式遍歷排序後的中間資料,對於每一個唯一的中間 key 值,Reduce worker 程式將這個 key 值和它相關的中間 value 值的集合傳遞給使用者自定義的 Reduce 函式。Reduce 函式的輸出被追加到所屬分割槽的輸出檔案。
- 當所有的 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 開發過程中學到了不少東西。首先,約束程式設計模式使得並行和分散式計算非常容易,也易於構造容錯的計算環境;其次,網路頻寬是稀有資源。大量的系統優化是針對減少網路傳輸量為目的的:本地優化策略使大量的資料從本地磁碟讀取,中間檔案寫入本地磁碟、並且只寫一份中間檔案也節約了頻寬;第三,多次執行相同的任務可以減少效能緩慢的機器帶來的負面影響,同時解決了由於機器失效導致的資料丟失問題。