由於沒找到谷歌的示意圖,因此我想借用一張Hadoop項目的結構圖來講明下MapReduce所處的位置,以下圖。java
Hadoop實際上就是谷歌三寶的開源實現,Hadoop MapReduce對應Google MapReduce,HBase對應BigTable,HDFS對應GFS。HDFS(或GFS)爲上層提供高效的非結構化存儲服務,HBase(或BigTable)是提供結構化數據服務的分佈式數據庫,Hadoop MapReduce(或Google MapReduce)是一種並行計算的編程模型,用於做業調度。c++
GFS和BigTable已經爲咱們提供了高性能、高併發的服務,可是並行編程可不是全部程序員都玩得轉的活兒,若是咱們的應用自己不能併發,那GFS、BigTable也都是沒有意義的。MapReduce的偉大之處就在於讓不熟悉並行編程的程序員也能充分發揮分佈式系統的威力。程序員
簡單歸納的說,MapReduce是將一個大做業拆分爲多個小做業的框架(大做業和小做業應該本質是同樣的,只是規模不一樣),用戶須要作的就是決定拆成多少份,以及定義做業自己。數據庫
下面用一個貫穿全文的例子來解釋MapReduce是如何工做的。編程
若是我想統計下過去10年計算機論文出現最多的幾個單詞,看看你們都在研究些什麼,那我收集好論文後,該怎麼辦呢?小程序
方法一:我能夠寫一個小程序,把全部論文按順序遍歷一遍,統計每個遇到的單詞的出現次數,最後就能夠知道哪幾個單詞最熱門了。緩存
這種方法在數據集比較小時,是很是有效的,並且實現最簡單,用來解決這個問題很合適。多線程
方法二:寫一個多線程程序,併發遍歷論文。併發
這個問題理論上是能夠高度併發的,由於統計一個文件時不會影響統計另外一個文件。當咱們的機器是多核或者多處理器,方法二確定比方法一高效。可是寫一個多線程程序要比方法一困難多了,咱們必須本身同步共享數據,好比要防止兩個線程重複統計文件。app
方法三:把做業交給多個計算機去完成。
咱們可使用方法一的程序,部署到N臺機器上去,而後把論文集分紅N份,一臺機器跑一個做業。這個方法跑得足夠快,可是部署起來很麻煩,咱們要人工把程序copy到別的機器,要人工把論文集分開,最痛苦的是還要把N個運行結果進行整合(固然咱們也能夠再寫一個程序)。
方法四:讓MapReduce來幫幫咱們吧!
MapReduce本質上就是方法三,可是如何拆分文件集,如何copy程序,如何整合結果這些都是框架定義好的。咱們只要定義好這個任務(用戶程序),其它都交給MapReduce。
在介紹MapReduce如何工做以前,先講講兩個核心函數map和reduce以及MapReduce的僞代碼。
map函數和reduce函數是交給用戶實現的,這兩個函數定義了任務自己。
統計詞頻的MapReduce函數的核心代碼很是簡短,主要就是實現這兩個函數。
[plain] view plain copy
在統計詞頻的例子裏,map函數接受的鍵是文件名,值是文件的內容,map逐個遍歷單詞,每遇到一個單詞w,就產生一箇中間鍵值對<w, "1">,這表示單詞w咱又找到了一個;MapReduce將鍵相同(都是單詞w)的鍵值對傳給reduce函數,這樣reduce函數接受的鍵就是單詞w,值是一串"1"(最基本的實現是這樣,但能夠優化),個數等於鍵爲w的鍵值對的個數,而後將這些「1」累加就獲得單詞w的出現次數。最後這些單詞的出現次數會被寫到用戶定義的位置,存儲在底層的分佈式存儲系統(GFS或HDFS)。
上圖是論文裏給出的流程圖。一切都是從最上方的user program開始的,user program連接了MapReduce庫,實現了最基本的Map函數和Reduce函數。圖中執行的順序都用數字標記了。
全部執行完畢後,MapReduce輸出放在了R個分區的輸出文件中(分別對應一個Reduce做業)。用戶一般並不須要合併這R個文件,而是將其做爲輸入交給另外一個MapReduce程序處理。整個過程當中,輸入數據是來自底層分佈式文件系統(GFS)的,中間數據是放在本地文件系統的,最終輸出數據是寫入底層分佈式文件系統(GFS)的。並且咱們要注意Map/Reduce做業和map/reduce函數的區別:Map做業處理一個輸入數據的分片,可能須要調用屢次map函數來處理每一個輸入鍵值對;Reduce做業處理一個分區的中間鍵值對,期間要對每一個不一樣的鍵調用一次reduce函數,Reduce做業最終也對應一個輸出文件。
我更喜歡把流程分爲三個階段。第一階段是準備階段,包括一、2,主角是MapReduce庫,完成拆分做業和拷貝用戶程序等任務;第二階段是運行階段,包括三、四、五、6,主角是用戶定義的map和reduce函數,每一個小做業都獨立運行着;第三階段是掃尾階段,這時做業已經完成,做業結果被放在輸出文件裏,就看用戶想怎麼處理這些輸出了。
結合第四節,咱們就能夠知道第三節的代碼是如何工做的了。假設我們定義M=5,R=3,而且有6臺機器,一臺master。
這幅圖描述了MapReduce如何處理詞頻統計。因爲map worker數量不夠,首先處理了分片一、三、4,併產生中間鍵值對;當全部中間值都準備好了,Reduce做業就開始讀取對應分區,並輸出統計結果。
用戶最主要的任務是實現map和reduce接口,但還有一些有用的接口是向用戶開放的。
目前MapReduce已經有多種實現,除了谷歌本身的實現外,還有著名的hadoop,區別是谷歌是c++,而hadoop是用java。另外斯坦福大學實現了一個在多核/多處理器、共享內存環境內運行的MapReduce,稱爲Phoenix(介紹),相關的論文發表在07年的HPCA,是當年的最佳論文哦!