1. 程式人生 > >MapReduce計算模型二

MapReduce計算模型二

中間 比較 microsoft bsp += 磁盤io 一般來說 一次 sof

之前寫過關於Hadoop方面的MapReduce框架的文章MapReduce框架Hadoop應用(一) 介紹了MapReduce的模型和Hadoop下的MapReduce框架,此文章將進一步介紹mapreduce計算模型能用於解決什麽問題及有什麽巧妙優化。

MapReduce到底解決什麽問題?

MapReduce準確的說,它不是一個產品,而是一種解決問題的思路,能夠用分治策略來解決問題。例如:網頁抓取、日誌處理、索引倒排、查詢請求匯總等等問題。通過分治法,將一個大規模的問題,分解成多個小規模的問題(分),多個小規模問題解決,再統籌小問題的解(合),就能夠解決大規模的問題。最早在單機的體系下計算,當輸入數據量巨大的時候,處理很慢。如何能夠在短時間內完成處理,很容易想到的思路是,將這些計算分布在成百上千的主機上,但此時,會遇到各種復雜的問題,例如:並發計算、數據分發、錯誤處理、數據分布、負載均衡、集群管理與通信等,將這些問題綜合起來將是比較復雜的問題了,而Google為了方便用戶使用系統,提供給了用戶很少的接口,去解決復雜的問題。

    (1) Map函數接口:處理一個基於key/value(後簡稱k/v)的數據對(pair)數據集合,同時也輸出基於k/v的數據集合。

    (2) Reduce函數接口:用來合並Map輸出的k/v數據集合

假設我們要統計大量文檔中單詞出現的次數

  Map

    輸入K/V:pair(文檔名稱,文檔內容)

    輸出K/V:pair(單詞,1)

  Reduce

    輸入K/V:pair(單詞,1)

    輸出K/V:pair(單詞,總計數) 

  Map偽代碼:

Map(list<pair($docName, $docContent)>){//如果有多個Map進程,輸入可以是一個pair,不是一個list
foreach(pair in list) foreach($word in $docContent) print pair($word, 1); // 輸出list<k,v> }

  Reduce偽代碼:

Reduce(list<pair($word, $count)>){//大量(word,1)(即使有多個Reduce進程,輸入也是list<pair>,因為它的輸入是Map的輸出)
    map<string,int> result;
        foreach(pair in list)
         if result.isExist($word)

             result[$word] += $count;          else              result[$word] = 1; foreach($keyin result) print pair($key, result[$key]); //輸出list<k,v> }

  技術分享圖片

  可以看到,R個reduce實例並發進行處理,直接輸出最後的計數結果。需要理解的是,由於這是業務計算的最終結果,一個單詞的計數不會出現在兩個實例裏。即:如果(a, 256)出現在了實例1的輸出裏,就一定不會出現在其他實例的輸出裏,否則的話,還需要合並,就不是最終結果。

  再看中間步驟,map到reduce的過程,M個map實例的輸出,會作為R個reduce實例的輸入。

  問題一:每個map都有可能輸出(a, 1),而最終結果(a, 256)必須由一個reduce輸出,那如何保證每個map輸出的同一個key,落到同一個reduce上去呢?

    這就是“分區函數”的作用。分區函數是使用MapReduce的用戶按所需實現的,決定map輸出的每一個key應當落到哪個reduce上的函數。如果用戶沒有實現,會使用默認分區函數。為了保證每一個reduce實例都能夠差不多時間結束工作任務,分區函數的實現要點是:盡量負載均衡,即數據均勻分攤,防止數據傾斜造成部分reduce節點數據饑餓。如果數據不是負載均衡的,那麽有些reduce實例處理的單詞多,有些reduce處理的單詞少,這樣就可能出現所有reduce實例都處理結束,最後等待一個需要長時間處理的reduce情況。

  問題二:每個map都有可能輸出多個(a, 1),這樣就增大了網絡帶寬資源以及reduce的計算資源,怎麽辦?

    這就是“合並函數”的作用。有時,map產生的中間key的重復數據比重很大,可以提供給用戶一個自定義函數,在一個map實例完成工作後,本地就做一次合並,這樣將大大節約網絡傳輸與reduce計算資源。合並函數在每個map任務結束前都會執行一次,一般來說,合並函數與reduce函數是一樣的,區別是:合並函數是執行map實例本地數據合並,而reduce函數是執行最終的合並,會收集多個map實例的數據。對於詞頻統計應用,合並函數可以將:一個map實例的多個(a, 1)合並成一個(a, count)輸出。

  問題三:如何確定文件到map的輸入呢?

    隨意即可,只要負載均衡,均勻切分輸入文件大小就行,不用管分到哪個map實例都能正確處理

  問題四:map和reduce可能會產生很多磁盤io,將更適用於離線計算,完成離線作業。

MapReduce計算模型二