圖解MapReduce工作流程



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


我們需要提供什麼





  1. 提供input locations和output location
    這個是在運行jar包的命令行中提供的.

  2. 提供map和reduce的實現
    這個對應源代碼中的TokenizerMapper和IntSumReducer類。

  3. 提供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


我們需要提供什麼





  1. 提供input locations和output location
    這個是在運行jar包的命令行中提供的.

  2. 提供map和reduce的實現
    這個對應源代碼中的TokenizerMapper和IntSumReducer類。

  3. 提供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 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章