MapReduce特點
整體結構
Hadoop工作架構
我們的應用程序通過Hadoop job client向Hadoop集羣提交作業,Hadoop集羣中Master節點負責調度各個Slave節點共同完成作業。
Hadoop job client是什麼?
我認爲有2個含義。1是在代碼中使用的api,2是提交作業時使用的命令行工具。
比如在參考文章中的WordCount v1.0源代碼,main方法負責構建配置並提交作業:
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
這裏大部分的類都來自包org.apache.hadoop.mapreduce。
而在運行這個程序的時候,先生成jar包,再執行下面的命令:
$ bin/hadoop jar wc.jar WordCount /user/joe/wordcount/input /user/joe/wordcount/output
我們需要提供什麼
-
提供input locations和output location
這個是在運行jar包的命令行中提供的. -
提供map和reduce的實現
這個對應源代碼中的TokenizerMapper和IntSumReducer類。 -
提供job參數
具體對應源代碼中的main方法.
包括上面的input/output locations, map和reduce的實現, 都需要以job參數的形式來提供, 才能實際被使用.
流程細節
flat
流水細節
client將軟件和數據提交給job,job將輸入拆分成一個個獨立的數據塊,每個數據塊提交給不同的map task來處理.
結合HDFS的內容,我推論實際的過程是這樣子的:
job查詢NameNode元數據,得知輸入數據文件對應的數據塊及其所在的DataNode位置.
然後將所要執行的軟件,和對應的數據塊的元數據信息傳給對應的DataNode.
每個DataNode所接收到的軟件是一樣的,但是數據塊的元數據信息就只是自己相關的那一部分.
DataNode接收軟件和數據塊元數據之後,就找出對應的數據,作爲輸入來執行軟件.
map對數據塊中的數據進行初次處理,由於每個map task處理的是不同的數據塊,所以這裏是並行的. 處理完之後輸出<key1, value1>形式的中間結果.
框架對中間結果進行處理,對每個中間結果進行排序,分區,發到具體的reduce task,然後再進行排序,分組.
最後reduce程序接收到的輸入是<key1, list<value1>>的格式,這是按照key進行分組的結果.
reduce負責處理<key1, list<value1>>, 並輸出最終的結果<key2, value2>到輸出目錄.
整個過程的數據類型變化情況
(input)<k0, v0> -> map -> <k1, v1> -> shuffle & sort -> <k1, list<v1>> -> reduce -> <k2, v2>(output)
map和reduce的個數
map task的個數 = input文件的所有的塊的個數.
reduce task的個數可以設置:Job.setNumReduceTasks();設置的大, 會增加框架開銷, 但是可以增加負載均衡 並降低故障成本(每一個reduce負責的內容少了). 設置的小則會有相反的結論.
分區和reduce個數
group
MapReduce的細節
淺綠色背景是我們要做的,其他是框架做的.
Map
-
map 是我們定義的map函數, 負責從我們指定的輸入中解析出作爲中間結果的<Key1, Value1>
-
sort 負責對map的結果進行排序
-
partition 負責對上一步的結果數據進行分區.不同的分區會發到不同的Reduce task.
-
combine 負責本地聚合數據,這樣可以減少發到Reduce task的數據量. 由我們自己定義聚合函數,這一步不是必須的.
Reduce
-
shuffle 通過HTTP接收分區數據
-
sort 對分區數據排序, 分組(考慮到不同Map發來的分區,可能有相同的key)
-
reduce 產生最終結果<Key2, Value2>
結合WordCount v1.0看流程
這裏結合WordCount v1.0運行過程來對工作流程中每一步的工作有個形象的瞭解.
demo處理過程
WordCount負責統計輸入文件中每個單詞的出現次數.
input有2個文件, 每個文件佔據一個數據塊(每個文件都那麼小), 所以會有2個map task分別處理一個數據塊.
map的結果是以此記錄哪個單詞出現了一次, 並沒有進行排序和聚合處理.
map到combine之間還有一段, 就是框架對數據進行了排序, combine接收到的已經是排序的結果.
combine負責在本地聚合, 它主要可以減少數據從map到reduce的傳輸量. 可以看到combine的輸出已經是排好序且做了聚合處理.
reduce負責對接收到的來自2個map的數據塊進行再分組, 排序, 聚合. 並最終輸出結果.
End
MapReduce特點
整體結構
Hadoop工作架構
我們的應用程序通過Hadoop job client向Hadoop集羣提交作業,Hadoop集羣中Master節點負責調度各個Slave節點共同完成作業。
Hadoop job client是什麼?
我認爲有2個含義。1是在代碼中使用的api,2是提交作業時使用的命令行工具。
比如在參考文章中的WordCount v1.0源代碼,main方法負責構建配置並提交作業:
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
這裏大部分的類都來自包org.apache.hadoop.mapreduce。
而在運行這個程序的時候,先生成jar包,再執行下面的命令:
$ bin/hadoop jar wc.jar WordCount /user/joe/wordcount/input /user/joe/wordcount/output
我們需要提供什麼
-
提供input locations和output location
這個是在運行jar包的命令行中提供的. -
提供map和reduce的實現
這個對應源代碼中的TokenizerMapper和IntSumReducer類。 -
提供job參數
具體對應源代碼中的main方法.
包括上面的input/output locations, map和reduce的實現, 都需要以job參數的形式來提供, 才能實際被使用.
流程細節
flat
流水細節
client將軟件和數據提交給job,job將輸入拆分成一個個獨立的數據塊,每個數據塊提交給不同的map task來處理.
結合HDFS的內容,我推論實際的過程是這樣子的:
job查詢NameNode元數據,得知輸入數據文件對應的數據塊及其所在的DataNode位置.
然後將所要執行的軟件,和對應的數據塊的元數據信息傳給對應的DataNode.
每個DataNode所接收到的軟件是一樣的,但是數據塊的元數據信息就只是自己相關的那一部分.
DataNode接收軟件和數據塊元數據之後,就找出對應的數據,作爲輸入來執行軟件.
map對數據塊中的數據進行初次處理,由於每個map task處理的是不同的數據塊,所以這裏是並行的. 處理完之後輸出<key1, value1>形式的中間結果.
框架對中間結果進行處理,對每個中間結果進行排序,分區,發到具體的reduce task,然後再進行排序,分組.
最後reduce程序接收到的輸入是<key1, list<value1>>的格式,這是按照key進行分組的結果.
reduce負責處理<key1, list<value1>>, 並輸出最終的結果<key2, value2>到輸出目錄.
整個過程的數據類型變化情況
(input)<k0, v0> -> map -> <k1, v1> -> shuffle & sort -> <k1, list<v1>> -> reduce -> <k2, v2>(output)
map和reduce的個數
map task的個數 = input文件的所有的塊的個數.
reduce task的個數可以設置:Job.setNumReduceTasks();設置的大, 會增加框架開銷, 但是可以增加負載均衡 並降低故障成本(每一個reduce負責的內容少了). 設置的小則會有相反的結論.
分區和reduce個數
group
MapReduce的細節
淺綠色背景是我們要做的,其他是框架做的.
Map
-
map 是我們定義的map函數, 負責從我們指定的輸入中解析出作爲中間結果的<Key1, Value1>
-
sort 負責對map的結果進行排序
-
partition 負責對上一步的結果數據進行分區.不同的分區會發到不同的Reduce task.
-
combine 負責本地聚合數據,這樣可以減少發到Reduce task的數據量. 由我們自己定義聚合函數,這一步不是必須的.
Reduce
-
shuffle 通過HTTP接收分區數據
-
sort 對分區數據排序, 分組(考慮到不同Map發來的分區,可能有相同的key)
-
reduce 產生最終結果<Key2, Value2>
結合WordCount v1.0看流程
這裏結合WordCount v1.0運行過程來對工作流程中每一步的工作有個形象的瞭解.
demo處理過程
WordCount負責統計輸入文件中每個單詞的出現次數.
input有2個文件, 每個文件佔據一個數據塊(每個文件都那麼小), 所以會有2個map task分別處理一個數據塊.
map的結果是以此記錄哪個單詞出現了一次, 並沒有進行排序和聚合處理.
map到combine之間還有一段, 就是框架對數據進行了排序, combine接收到的已經是排序的結果.
combine負責在本地聚合, 它主要可以減少數據從map到reduce的傳輸量. 可以看到combine的輸出已經是排好序且做了聚合處理.
reduce負責對接收到的來自2個map的數據塊進行再分組, 排序, 聚合. 並最終輸出結果.
End