1 什么是MapReduce?
Map本意可以理解為地圖,映射(面向對象語言都有Map集合),這里我們可以理解為從現實世界獲得或產生映射。Reduce本意是減少的意思,這里我們可以理解為歸並前面Map產生的映射。
2 MapReduce的編程模型
按照google的MapReduce論文所說的,MapReduce的編程模型的原理是:利用一個輸入key/value對集合來產生一個輸出的key/value對集合。MapReduce庫的用戶用兩個函數表達這個計算:Map和Reduce。用戶自定義的Map函數接受一個輸入的key/value對值,然后產生一個中間key/value對值的集合。MapReduce庫把所有具有相同中間key值的中間value值集合在一起后傳遞給Reduce函數。用戶自定義的Reduce函數接受一個中間key的值和相關的一個value值的集合。Reduce函數合並這些value值,形成一個較小的value值的集合。
3 MapReduce實現
通過將Map調用的輸入數據自動分割為M個數據片段的集合,Map調用被分布到多台機器上執行。輸入的數據片段能夠在不同的機器上並行處理。使用分區函數將Map調用產生的中間key值分成R個不同分區(例如,hash(key) mod R),Reduce調用也被分布到多台機器上執行。分區數量(R)和分區函數由用戶來指定。
MapReduce實現的大概過程如下:
1.用戶程序首先調用的MapReduce庫將輸入文件分成M個數據片度,每個數據片段的大小一般從16MB到64MB(可以通過可選的參數來控制每個數據片段的大小)。然后用戶程序在集群中創建大量的程序副本。
2.這些程序副本中的有一個特殊的程序master。副本中其它的程序都是worker程序,由master分配任務。有M個Map任務和R個Reduce任務將被分配,master將一個Map任務或Reduce任務分配給一個空閑的worker。
3.被分配了map任務的worker程序讀取相關的輸入數據片段,從輸入的數據片段中解析出key/value對,然后把key/value對傳遞給用戶自定義的Map函數,由Map函數生成並輸出的中間key/value對,並緩存在內存中。
4.緩存中的key/value對通過分區函數分成R個區域,之后周期性的寫入到本地磁盤上,會產生R個臨時文件。緩存的key/value對在本地磁盤上的存儲位置將被回傳給master,由master負責把這些存儲位置再傳送給Reduce worker。
5.當Reduce worker程序接收到master程序發來的數據存儲位置信息后,使用RPC從Map worker所在主機的磁盤上讀取這些緩存數據。當Reduce worker讀取了所有的中間數據(這個時候所有的Map任務都執行完了)后,通過對key進行排序后使得具有相同key值的數據聚合在一起。由於許多不同的key值會映射到相同的Reduce任務上,因此必須進行排序。如果中間數據太大無法在內存中完成排序,那么就要在外部進行排序。
6.Reduce worker程序遍歷排序后的中間數據,對於每一個唯一的中間key值,Reduce worker程序將這個key值和它相關的中間value值的集合(這個集合是由Reduce worker產生的,它存放的是同一個key對應的value值)傳遞給用戶自定義的Reduce函數。Reduce函數的輸出被追加到所屬分區的輸出文件。
上面過程中的排序很容易理解,關鍵是分區,這一步最終決定該鍵值對未來會交給哪個reduce任務,如統計單詞出現的次數可以用前面說的hash(key) mod R來分區,如果是對數據進行排序則應該根據key的分布進行分區。
圖1 MapReduce過程
4 例子
假設我們需要處理一批有關天氣的數據,其格式如下: 按照ASCII碼存儲,每行一條記錄,每一行字符從0開始計數,第15個到第18個字符為年,第25個到第29個字符為溫度,其中第25位是符號+/-,現在需要統計出每年的最高溫度。
0067011990999991950051507+0000+
0043011990999991950051512+0022+
0043011990999991950051518-0011+
0043012650999991949032412+0111+
0043012650999991949032418+0078+
0067011990999991937051507+0001+
0043011990999991937051512-0002+
0043011990999991945051518+0001+
0043012650999991945032412+0002+
0043012650999991945032418+0078+
MapReduce主要包括兩個步驟:Map和Reduce 每一步都有key/value對作為輸入和輸出:
Map階段的key/value對的格式是由輸入的格式所決定的,如果是默認的TextInputFormat,則每行作為一個記錄進程處理,其中key為此行的開頭相對於文件的起始位置,value就是此行的字符文本,Map階段的輸出的key/value對的格式必須同Reduce階段的輸入key/value對的格式相對應
對於上面的例子,在map過程,輸入的key-value對如下:
(0 ,0067011990999991950051507+0000+)
(1 ,0043011990999991950051512+0022+)
(2 ,0043011990999991950051518-0011+)
(3 ,0043012650999991949032412+0111+)
(4 ,0043012650999991949032418+0078+)
(5 ,0067011990999991937051507+0001+)
(6 ,0043011990999991937051512-0002+)
(7 ,0043011990999991945051518+0001+)
(8 ,0043012650999991945032412+0002+)
(9 ,0043012650999991945032418+0078+)
將上面的數據作為用戶編寫的map函數的輸入,通過對每一行字符串的解析,得到年/溫度的key/value對作為輸出:
(1950, 0)
(1950, 22)
(1950, -11)
(1949, 111)
(1949, 78)
(1937, 1)
(1937, -2)
(1945, 1)
(1945, 2)
(1945, 78)
在Reduce過程,將map過程中的輸出,按照相同的key將value放到同一個列表中作為用戶寫的reduce函數的輸入
(1950, [0, 22, –11])
(1949, [111, 78])
(1937, [1, -2])
(1945, [1, 2, 78])
在Reduce過程中,在列表中選擇出最大的溫度,將年/最大溫度的key/value作為輸出:
(1950, 22)
(1949, 111)
(1937, 1)
(1945, 78)
其邏輯過程可用如下圖表示:
參考:
http://desert3.iteye.com/blog/865243
http://www.cnblogs.com/duguguiyu/archive/2009/02/28/1400278.html
http://www.cnblogs.com/MitiskySean/p/3320451.html
<<MapReduce: Simplied Data Processing on Large Clusters>>