谷歌在2003到2006年間連續發表了三篇非常有影響力的文章,分別是2003年在SOSP上發布的GFS,2004年在OSDI上發布的MapReduce,以及2006年在OSDI上發布的BigTable。GFS是文件系統相關的,其對後來的分布式文件系統設計具有指導意義;MapReduce是一種並行計算的編程模型,用於作業調度;BigTable是一個用於管理結構化數據的分布式存儲系統,構建在GFS、Chubby、SSTable等Google技術之上。相當多的Google應用使用了這三種技術,比如Google Search、Google Earth和Google Analytics等等。因此這三種技術並稱為谷歌技術”三寶”。今天,D瓜哥班門弄斧,對MapReduce來個”庖丁解牛”!
MapReduce簡介
MapReduce是一個編程模型,也是一個處理和生成超大數據集的算法模型的相關實現。用戶首先創建一
個Map函數處理一個基於key/value pair的數據集合,輸出中間的基於key/value pair的數據集合;然後
再創建一個Reduce函數用來合並所有的具有相同中間key值的中間value值。
一圖勝千言,下面我們用一張圖來說明一下MapReduce:
編程實踐
常言道:”實踐出真知” 。是騾子是馬,拉出來遛遛才知道。所以,如果真的想搞懂這個原理,還是親自寫代碼實踐一下才是硬道理。
最近和幾個朋友一起學習JavaScript,所以就比較關注JavaScript。昨天上網瞎逛時,驚奇地發現,竟然有牛人使用JavaScript實現了MapReduce算法。然後轉過來和大家分享,同時再加上我自己的一些狗尾續貂的介紹,希望有助於大家理解MapReduce。具體代碼實現如下:
復制代碼 代碼如下:
var Job = {
//待處理的數據
data : [
"We are glad to see you here. This site is dedicated to",
"poetry and to the people who make poetry possible",
"poets and their readers. FamousPoetsAndPoems.com is",
"a free poetry site. On our site you can find a large",
"collection of poems and quotes from over 631 poets",
"Read and Enjoy Poetry",
"I, too, sing America",
"I am the darker brother",
"They send me to eat in the kitchen",
"When company comes",
"But I laugh",
"And eat well",
"And grow strong",
"Tomorrow",
"Ill be at the table",
"When company comes",
"Nobodyll dare",
"Say to me",
"Eat in the kitchen",
"Then",
"Besides",
"Theyll see how beautiful I am",
"And be ashamed",
"I, too, am America"
],
//將數據中的每行字符串用空格分隔開,
//並"重組"成諸如{key: 單詞, value: 1}格式的對象,返回對象數組
map : function(line) {
var splits = line.split(" ");
var temp = [];
for(var i=0; i<splits.length; i++) {
temp.push({key : splits[i], value : 1});
}
return temp;
},
//計算每個單詞在"數據"(data)中出現的次數
reduce : function(allSteps) {
var result = {};
for(var i=0; i<allSteps.length; i++) {
var step = allSteps[i];
result[step.key] = result[step.key] ? (result[step.key] + 1) : 1;
}
return result;
},
//初始化,同時是運行的入口。
init : function() {
var allSteps = [];
for(var i=0; i<Job.data.length; i++) {
//如果這裡能多線程調用Job.map函數就更逼真了。??
allSteps = allSteps.concat(Job.map(Job.data[i]));
}
//美中不足,這裡不能多線程調用Job.reduce函數??
var result = Job.reduce(allSteps)
console.log(JSON.stringify(result));
}
}; // Job
//開始執行
Job.init();
復制這些代碼,直接粘貼到浏覽器的控制台(Console)中,或者放到一個HTML文件中,用浏覽器打開,就可以在控制台輸出中,看到效果如下:
美中不足
這篇文章發布出來之後,就有網友“咆哮”:“一個連多線程都沒有的js 搞什麼MapReduce啊?”其實,這個問題,D瓜哥也發現了。在看到這個代碼的解釋後,D瓜哥就納悶JavaScript不是單進程嗎?怎麼還能模擬MapReduce?在認真閱讀代碼,單步調試之後,更加印證了D瓜哥的看法。(關於D瓜哥的疑問已經在代碼中注釋出來。)
不過,再想一下,這些並不影響我們去理解MapReduce的原理。這只是個單進程,最基礎的版本。先理解了這個,再去整個多線程的也許就更容易理解了。
未完待續
其實,D瓜哥現在考慮在這個例子的基礎上,用Java實現一個多線程版本,那樣模擬的MapReduce更逼真。等D瓜哥把一些問題思考清楚之後,就把代碼發出來。敬請期待!