本文是MapReduce論文的學習筆記。MapReduce框架須要使用者提供map和reduce函數,map函數將一個鍵/值輸入轉換成一組中間鍵/值,而後reduce函數將全部具備相同鍵的中間鍵值對進行合併,而其餘的任務調度、文件分割、容錯處理等工做都由框架來完成。編程
MapReduce框架用戶須要提供兩個函數map和reduce:app
初看很難體會到MapReduce的設計初衷,而MapReduce最經典的例子就是單詞計數任務,單詞計數任務的兩個函數定義以下:框架
func map(filename string, contents string) []mapreduce.KeyValue {
words := strings.FieldsFunc(contents, func(r rune) bool {
return !unicode.IsLetter(r)
})
var res []mapreduce.KeyValue
for _, word := range words {
res = append(res, mapreduce.KeyValue{ Key:word, Value:"1" })
}
return res
}
func reduce(key string, values []string) string {
result := 0
for _, value := range values {
count, _ := strconv.Atoi(value)
result += count
}
return strconv.Itoa(result)
}
複製代碼
上述例子中map函數輸入鍵爲文件名,輸入值爲文件內容,map函數將文件內容分割爲多個單詞,中間鍵值對爲單詞和單詞出現次數「1」,而reduce函數將某個單詞全部出現的次數相加。分佈式
除了最簡單的單詞統計之外,還有不少的問題均可以套用MapReduce的模型解決。函數
<URL,1>
,reduce函數將URL的全部中間鍵值對的值相加,產生結果<URL,訪問次數>
。<目標,來源>
。Reduce函數合併相同目標的中間值,產生<目標,list(來源)>
。<單詞,文檔編號>
的中間鍵值對,而後reduce函數合併中間鍵值對,產生結果<單詞,list(文檔編號)>
。最終結果組成一個反向索引,能夠用於查詢單詞出現的文檔。<鍵,記錄>
,reduce函數則原樣輸出中間鍵值對便可。MapReduce須要處理的數據會被事先分割爲M片斷,中間數據被分配給R個片斷,分割過程由分割函數hash(鍵) mod R
,分片數M和R以及哈希函數都由用戶定義。學習
MapReduce處理結果一般會被保存到R個文件片斷中,文件片斷一般不須要被合併,直接用於其餘的分佈式任務。優化
Master會不斷ping各個worker,若是某個worker產生錯誤,那麼會被重置到可調度狀態。發生錯誤的時候,已經完成的map任務須要被從新執行,由於map的結果保存到本地磁盤中,而已完成的reduce任務不須要被從新執行,由於reduce任務的結果被寫入全局文件系統,ui
可讓master按期將狀態保存到磁盤,崩潰後直接利用保存的狀態恢復。另外,也能夠考慮直接在master奔潰的時候終止MapReduce任務。spa
在實現MapReduce實現中,由不少的技巧能夠提升系統的運行效率。設計
<the,1>
這樣經常使用詞產生的中間數據傳遞給某個reduce任務的worker,這會給某個worker帶來巨大的負擔。解決的方法就是讓map執行完成後調用合併函數處理一編中間數據。合併函數和reduce函數一般是同樣的,只是調用場景不一樣。