Google MapReduce研究綜述
MapReduce研究探討體會
MapReduce : Simplified Data Processing on Large Clusters
MapReduce基礎 未讀
Hadoop 分散式運算技術專題
Nutch 是最早用MapReduce的項目 (Hadoop其實原來是Nutch的一部分),Nutch的plugin機制吸取了eclipse的plugin設計思路。
在Nutch中 MapReduce編程方式佔據了其核心的結構大部分。從插入url列表(Inject),產生抓取列表(Generate),抓取內容(Fetch), 分析處理內容(Parse),更新Crawl DB庫(Update ),轉化連結(Invert Links)一直到建立索引(Index)都是採用MapReduce來完成的。查看Nutch的原始碼我們能夠學到更多的 如何用MapReduce來處理我們編程中所遇到的問題。
Nutch從擷取下載列表到建立索引的過程:
插入url列表到Crawl DB,引導下面的抓取程式
迴圈:
– 從Crawl DB產生一些url列表;
– 抓取內容;
– 分析處理抓取的內容;
– 更新Crawl DB庫.
轉化每個頁面中外部對它的連結
建立索引
具體技術實現細節:
1。插入url列表(Inject)
MapReduce程式1:
目標:轉換input輸入為CrawlDatum格式.
輸入: url檔案
Map(line) → <url, CrawlDatum>
Reduce()合并多重的Url.
輸出:臨時的CrawlDatum檔案.
MapReduce2:
目標:合并上一步產生的臨時檔案到新的DB
輸入: 上次MapReduce輸出的CrawlDatum
Map()過濾重複的url.
Reduce: 合并兩個CrawlDatum到一個新的DB
輸出:CrawlDatum
2。產生抓取列表(Generate)
MapReduce程式1:
目標:選擇抓取列表
輸入: Crawl DB 檔案
Map() → 如果抓取目前時間大於現在時間 ,抓換成 <CrawlDatum, url>格式.
分發器(Partition) :用url的host保證同一個網站分發到同一個Reduce程式上.
Reduce:取最頂部的N個連結.
MapReduce程式2:
目標:準備抓取
Map() 抓換成 <url,CrawlDatum,>格式
分發器(Partition) :用url的host
輸出:<url,CrawlDatum>檔案
3。抓取內容(Fetch)
MapReduce:
目標:抓取內容
輸入: <url,CrawlDatum>, 按host劃分, 按hash排序
Map(url,CrawlDatum) → 輸出<url, FetcherOutput>
多線程, 調用Nutch的抓取協議外掛程式,抓取輸出<CrawlDatum, Content>
輸出: <url,CrawlDatum>, <url,Content>兩個檔案
4。分析處理內容(Parse)
MapReduce:
目標:處理抓取的能容
輸入: 抓取的<url, Content>
Map(url, Content) → <url, Parse>
調用Nutch的解析外掛程式,輸出處理完的格式是<ParseText, ParseData>
輸出: <url,ParseText>, <url,ParseData><url,CrawlDatum>.
5。更新Crawl DB庫(Update )
MapReduce:
目標: 整合 fetch和parse到DB中
輸入:<url,CrawlDatum> 現有的db加上fetch和parse的輸出,合并上面3個DB為一個新的DB
輸出: 新的抓取DB
6。轉化連結(Invert Links)
MapReduce:
目標:統計外部頁面對本頁面連結
輸入: <url,ParseData>, 包含頁面往外的連結
Map(srcUrl, ParseData> → <destUrl, Inlinks>
搜集外部對本頁面的連結Inlinks格式:<srcUrl, anchorText>
Reduce() 添加inlinks
輸出: <url, Inlinks>
7。建立索引(Index)
MapReduce:
目標:產生Lucene索引
輸入: 多種檔案格式
parse處理完的<url, ParseData> 提取title, metadata資訊等
parse處理完的<url, ParseText> 提取text內容
轉換連結處理完的<url, Inlinks> 提取anchors
抓取內容處理完的<url, CrawlDatum> 提取抓取時間.
Map() 用ObjectWritable包裹上面的內容
Reduce() 調用Nutch的索引外掛程式,產生Lucene Document文檔
輸出: 輸出Lucene索引
本文來自 http://www.hadoop.org.cn/mapreduce/nutch-mapreduce/
***************************************************************************************
Crawl the Nutch -- Map Reduce
初見於Google Lab的Paper, http://labs.google.com/papers/mapreduce.html ,論文中表明在有大量叢集支撐的情況下,可以快速的在海量文檔中進行資料處理。現在你有一堆資料,你需要按記錄修改、查詢、插入和刪除,一種辦法是你為這些記錄建立索引,比如放入資料庫,還有一種辦法就是--MapReduce。這種處理方式實際上是在資料存放的時候不建立索引,等實際處理資料的時候再將這些資料讀入記憶體進行排序,並可以用Partitioner將資料分在不同的機器上同時進行處理,因此可以方便的實現叢集計算,我猜想在一台機器上存放的資料容量以能夠全部裝進記憶體為限。
MapReduce把對資料記錄的所有操作都歸結兩個步驟--Map和Reduce。其中Map對現有資料做一個先期處理,
得到一個中間資料集,Reduce再對中間資料集進行去重、過濾等後期處理,最後得到你要的結果。Hadoop是一個MapReduce的實現,Nutch項目的大容量資料處理等功能就構建在Hadoop之上。
過程原形:
Map :: (InitialKey, IntialValue) -> [(InterKey, InterValue)]
Reduce :: (Interkey, InterValuesIterator) -> [(InterKey, InterValue)]
Map接收一個Key、Value對,返回一個Key、Value對(如果原始的Key、Value對不滿足你的要求你可以不返回,或者你有特殊需求也可以返回多個,一般比較少見), Reduce接收一個Key和一個Values的Iterator,你可以根據情況返回零個或多個Key,Value對。Key是一個實現了org.apache.hadoop.WritableComparable介面的類,Value則實現了Writable,WritableComparable是Writable的子介面,Writable定義了輸入輸出(序列化)的介面,WritableComparable另外繼承Comparable,因此Key總是有序的。
一個使用MapReduce的功能塊典型結構如下:
建立一個JobConf
設定輸入路徑
設定輸入檔案格式
設定輸入Key,Value類型
設定輸出路徑
設定輸出檔案格式
設定輸出Key,Value類型
設定Partitioner
啟動Job
執行完畢,你所有存放在輸入路徑下的資料都在被轉換之後按照你指定的格式存放於輸出路徑中,
ok,我知道很多人都是看code比看document更興奮,很不幸,我也是其中一員。
. 排序
比如你有一批URL,存放在文字檔c:/tmp/tmpin/urllist.txt中,一行一個
http://www.sohu.com
http://www.163.com
http://www.sina.com.cn
...
輸入格式一般是SequenceFileInputFormat,但是對於urllist.txt這種按行排列的格式卻是另外一種(我不知道的)格式,簡單來說就是你不需要設定輸入格式就能處理它了,在MapReduce傳遞給你的Map時,你可以忽略Key值,
而Value就是URL了,然後你做一個轉換把Value(URL)作為Key來存放,然後你自己合成一個Value值,比如只是簡單的一個數字1,或者是一個URL的相關資訊,DocumentId, 預計抓取時間等。因為這次的任務是排序,而事實上經過Map處理後資料已經是按Key(URL)排好序了,所以Reduce可以什麼也不做。
public class Main {
public static class InjectMapper extends MapReduceBase implements Mapper {
public void map(WritableComparable key, Writable val,
OutputCollector output, Reporter reporter) throws IOException {
UTF8 url = (UTF8) val;
UTF8 v = new UTF8("1");
output.collect(url, v); //產生資料
}
}
public static void main(String[] args) throws IOException {
JobConf job = new JobConf();
Path urlsPath = new Path("C:/tmp/tmpin");
job.setInputPath(urlsPath);
Path outputPath = new Path("c:/tmp/tmpout");
job.setOutputPath(outputPath);
job.setOutputFormat(SequenceFileOutputFormat.class);
job.setOutputKeyClass(UTF8.class);
job.setOutputValueClass(UTF8.class);
job.setMapperClass(InjectMapper.class);
//job.setReduceClass(InjectReducer.class);
JobClient.runJob(job);
}
}
. 去重
你的原始URL列表中可能有相同的URL,去除相同Key值記錄的功能就需要Reduce了,定義一個類
public static class InjectReducer extends MapReduceBase implements Reducer {
public void reduce(WritableComparable key, Iterator values,
OutputCollector output, Reporter reporter) throws IOException {
output.collect(key, (Writable) values.next());
}
}
並傳遞給JobConf就Ok了,由此可以看出Reduce過程對於同一個Key只被調用一次,那個values的Iterator包含這個Key所對應的全部記錄,你可以簡單的只取第一條資料,對這些記錄進行比較,得到你認為最有效一條記錄,或者統計每一個Key都有多少條記錄,一句話,你可以做任何事情(事實上是任何MapReduce所支援的事情)。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/wilbur727/archive/2007/09/26/1801699.aspx
Hadoop學習筆記一 簡要介紹
本文大部分內容都是從官網Hadoop上來的。其中有一篇介紹HDFS的pdf文檔,裡面對Hadoop介紹的比較全面了。我的這一個系列的Hadoop學習筆記也是從這裡一步一步進行下來的,同時又參考了網上的很多文章,對學習Hadoop中遇到的問題進行了歸納總結。
言歸正傳,先說一下Hadoop的來龍去脈。談到Hadoop就不得不提到Lucene和Nutch。首先,Lucene並不是一個應用程式,而是提供了一個純Java的高效能全文索引引擎工具包,它可以方便的嵌入到各種實際應用中實現全文檢索搜尋/索引功能。Nutch是一個應用程式,是一個以Lucene為基礎實現的搜尋引擎應用,Lucene為Nutch提供了文本搜尋和索引的API,Nutch不光有搜尋的功能,還有資料抓取的功能。在nutch0.8.0版本之前,Hadoop還屬於Nutch的一部分,而從nutch0.8.0開始,將其中實現的NDFS和MapReduce剝離出來成立一個新的開源項目,這就是Hadoop,而nutch0.8.0版本較之以前的Nutch在架構上有了根本性的變化,那就是完全構建在Hadoop的基礎之上了。在Hadoop中實現了Google的GFS和MapReduce演算法,使Hadoop成為了一個分布式的計算平台。
其實,Hadoop並不僅僅是一個用於儲存的Distributed File System,而是設計用來在由通用計算裝置組成的大型叢集上執行分布式應用的架構。
Hadoop包含兩個部分:
1、HDFS
即Hadoop Distributed File System (HadoopDistributed File System)
HDFS具有高容錯性,並且可以被部署在低價的硬體裝置之上。HDFS很適合那些有大資料集的應用,並且提供了對資料讀寫的高吞吐率。HDFS是一個master/slave的結構,就通常的部署來說,在master上只運行一個Namenode,而在每一個slave上運行一個Datanode。
HDFS支援傳統的層次檔案組織圖,同現有的一些檔案系統在操作上很類似,比如你可以建立和刪除一個檔案,把一個檔案從一個目錄移到另一個目錄,重新命名等等操作。Namenode管理著整個Distributed File System,對檔案系統的操作(如建立、刪除檔案和檔案夾)都是通過Namenode來控制。
下面是HDFS的結構:
{
function onclick()
{
get_larger(this)
}
}" src="http://img.ddvip.com/2008_09_18/1221727534_ddvip_2366.jpg" alt="Hadoop學習筆記一 簡要介紹">
從上面的圖中可以看出,Namenode,Datanode,Client之間的通訊都是建立在TCP/IP的基礎之上的。當Client要執行一個寫入的操作的時候,命令不是馬上就發送到Namenode,Client首先在本機上臨時檔案夾中緩衝這些資料,當臨時檔案夾中的資料區塊達到了設定的Block的值(預設是64M)時,Client便會通知Namenode,Namenode便響應Client的RPC請求,將檔案名稱插入檔案系統層次中並且在Datanode中找到一塊存放該資料的block,同時將該Datanode及對應的資料區塊資訊告訴Client,Client便這些本地臨時檔案夾中的資料區塊寫入指定的資料節點。
HDFS採取了副本策略,其目的是為了提高系統的可靠性,可用性。HDFS的副本放置策略是三個副本,一個放在本節點上,一個放在同一機架中的另一個節點上,還有一個副本放在另一個不同的機架中的一個節點上。目前的版本的hadoop0.12.0中還沒有實現,但是進行中中,相信不久就可以出來了。
2、MapReduce的實現
MapReduce是Google 的一項重要技術,它是一個編程模型,用以進行大資料量的計算。對於大資料量的計算,通常採用的處理手法就是並行計算。至少現階段而言,對許多開發人員來說,並行計算還是一個比較遙遠的東西。MapReduce就是一種簡化並行計算的編程模型,它讓那些沒有多少並行計算經驗的開發人員也可以開發並行應用。
MapReduce的名字源於這個模型中的兩項核心操作:Map和 Reduce。也許熟悉Functional Programming(函數式編程)的人見到這兩個詞會倍感親切。簡單的說來,Map是把一組資料一對一的映射為另外的一組資料,其映射的規則由一個函數來指定,比如對[1, 2, 3, 4]進行乘2的映射就變成了[2, 4, 6, 8]。Reduce是對一組資料進行歸約,這個歸約的規則由一個函數指定,比如對[1, 2, 3, 4]進行求和的歸約得到結果是10,而對它進行求積的歸約結果是24。
關於MapReduce的內容,建議看看孟岩的這篇MapReduce:The Free Lunch Is Not Over!
好了,作為這個系列的第一篇就寫這麼多了,我也是剛開始接觸Hadoop,下一篇就是講Hadoop的部署,談談我在部署Hadoop時遇到的問題,也給大家一個參考,少走點彎路。
來源:http://www.cnblogs.com/wayne1017/archive/2007/03/18/668768.html
**********************************************************************************
MapReduce: 一個巨大的倒退