Map 和 Reduce的概念介紹
MapReduce的創意和靈感來源於函數式編程。map和reduce是函數式編程中兩個常用函數。在函數式編程中,map函數對列表的每個元素執行操作或函數。例如,在列表[1, 2, 3, 4]上執行multiple-by-two函數會產生另一個列表[2, 4, 6, 8]。執行這些函數時,原有列表不會被修改。函數式編程認為應當保持數據不可變,避免在多個進程或線程間共享數據。這意味着剛演示過的map函數雖然很簡單,卻可以通過兩個或更多線程在同一個列表上同時執行,線程之間互不影響,因為列表本身沒有改變。
與map函數類似,函數式編程中還有一個reduce函數的概念。實際上,reduce在函數式編程中更廣為人知的名字是fold函數。reduce或fold函數又稱accumulate、compress或者inject函數。reduce或fold函數對數據結構(例如列表)中的所有元素執行一個函數,最終返回單個結果或輸出。因此在map函數輸出列表[2, 4, 6, 8]上執行reduce求和,會得到單個輸出值20。
map和reduce函數可以結合起來處理列表數據,先對列表的每個成員執行一個函數,再對轉換生成的列表執行另一個聚合函數。
map和reduce這種簡潔的思路可以用在大數據集上,只需稍事修改以適應由元組(tuple)或鍵值對組成的集合即可。map函數對集合中的每組鍵值對執行函數並產生一個新集合,接着reduce函數對新生成的集合執行聚合以計算最終結果。一個例子勝過千言萬語,下面我通過一個簡單的例子來解釋整個過程。假設存在由鍵值對組成的集合:
[{"94303":"Tom"},{"94303":"Jane"},{"94301":"Arun"},{"94302":"Chen"}]
其中鍵是郵政編碼,值是郵編指代范圍內居民的姓名。假設在集合上執行某map函數可以獲取特定郵編范圍內所有居民的姓名,則此map函數輸出如下:
[{"94303":["Tom","Jane"]},{"94301":["Arun"]},{"94302":["Chen"]}]
接着對上面的輸出執行某reduce函數以計算特定郵編范圍內居民的總數,最終輸出如下:
[{"94303":2},{"94301":1},{"94302":1}]
與任務並行的概念對比
1.模型應該和多線程類似,幾個互相沒有依賴的任務獨立執行。只是多線程是縱向擴展,MapReduce模型是橫向擴展。
2.為了能在不同節點傳輸數據,必須能序列化。為了更好的實現序列化,因此不用JAVA中實現的數據結構,比如用Text代替String。
適合的場景,可以拆分成若干任務,任務間沒有前后依賴關系
1.查詢最熱門的幾個詞
- 每個任務先統計詞出現的頻率
- 把每個任務的統計結果匯總,然后取前K個
2.貝葉斯分類
貝葉斯分類是一種利用概率統計知識進行分類的統計學分類方法。該方法分為兩個步驟:訓練樣本和分類。
可以用是三個MapReduce作業實現。
不適合的場景
前后有依賴關系的場景,比如說最典型的斐波那契數列就不適合。
