MapReduce 的抽象受到LIsp和其餘函數式語言你中的map和reduce原語的啓發。map和reduce(fold)函數都是屬於在函數式編程語言中的高階函數。map函數的功能是接受一個列表list以及一個函數,將這個函數做用於這個列表中的全部成員,並返回所得結果。例如,下述函數將括號中的三個數每一個加一:
map(+1)[1,2,3]
這個表達式的輸出結果是[2,3,4]。
而fold函數的功能則是接收一個列表、一個初始值以及一個函數,將該函數做爲特定的組合方式,將其遞歸地應用於列表的全部成員,並返回最終結果,好比,下述函數計算0+1+2+3的和:
fold(+)0[1,2,3]
其具體的操做流程是(((0+1)+2)+3),並最終返回其總和。一樣,也能夠用fold求一個列表的全部元素之積:
fold(*)1[1,2,3]
還繼續用上面統計單詞次數的例子,MapReduce計算模型裏的map函數實際上至關於下述函數式編程語言的語句:
map(f)[<k1,v1>,<k2,v2>,<k3,v3>,...]
其中f爲用戶實現的mapper函數裏的操做,因此咱們能夠看出,它本質上就是函數式編程中的map函數合成的操做。
讓咱們用Haskell的例子說明reduce函數,其功能就是分別求若干個數組中數字的積:
Prelude> let a=[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
Prelude> map(foldr(*)1)a
[6,120,504,1320]編程
做爲類比,能夠把MapReduce計算模型裏的reduce抽象成下述形式,根據鍵將鍵值對分組,而後分別計算:
let Internediate=[[<k1,v1>,<k1,v2>,<k1,v3>...],[<k2,v1>,<k2,v2>,<k2,v3>...]...]
map(reduce(f)[])Intermediate
只不過這裏,map步驟是由partitioner來實現分發不一樣鍵組的動做,而實際上對於每個reducer來講,它的工做方式正像是函數式編程裏的reducer同樣,對每個鍵值組採用用戶寫的f做爲特定的組合方式。
綜上所述,函數式語言與Hadoop這類系統中的map和reduce函數並無本質區別。做爲計算模型而言,MapReduce實際上就是函數式編程語言中的map和reduce函數的並行化拓展。另外,咱們能夠從MapReduce計算模型身上到處體會到函數式編程的哲學原理,即把數據抽象做爲一個流來進行操做,而顯然這種抽象也正是並行化的基礎。
從抽象的觀點看,一個流也就是一個序列。流處理使咱們能夠模擬一些包含狀態的系統,但卻不須要利用複製或者變更數據。這一狀況會產生一些重要的結果,既有理論的也有實際的。由於咱們能夠構造出一些模型,它們能避免因爲引進賦值而帶來的內在缺陷。可是,流框架也形成了它本身的困難。
數組