mr原理簡單分析

xiaoyon發表於2020-08-23

背景

     又是一個週末一天一天的過的好快,今天的任務幹啥呢,索引總結一些mr吧,因為前兩天有面試問過我?我當時也是簡單說了一下,畢竟現在寫mr程式的應該很少很少了,廢話不說了,結合官網和自己理解寫起。

 

官網 https://hadoop.apache.org/docs/r3.3.0/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html

 

簡單分析

一個mr作業通常資料會被切割成多個資料塊通過map任務來並行處理,就是說我們在處理檔案的時候,首次我們寫入檔案會被分割成多個塊,hdfs檔案設計支援的語義 write-once-read-moreblock塊是128m預設 https://hadoop.apache.org/docs/r3.3.0/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html Data Blocks 位置。然後在我們讀取的時候也就是提交mr 作業後namenode會根據後設資料管理然後從不同的datanode得知資料位置,從而進行讀取。mr框架包含一個單獨的master ResouceManager,每個叢集結點一個工作NodeManager,每個應用一個MRAppMaster

Input output,接受《keyvalue》最後落地《keyvalue》形式,需要實現Writetable介面,還要實現WritebaleCompare介面因為要對比排序。

 

public class WordCount {

 

  public static class TokenizerMapper

       extends Mapper<Object, Text, Text, IntWritable>{

 

    private final static IntWritable one = new IntWritable(1);

    private Text word = new Text();

 

    public void map(Object key, Text value, Context context

                    ) throws IOException, InterruptedException {

      StringTokenizer itr = new StringTokenizer(value.toString());

      while (itr.hasMoreTokens()) {

        word.set(itr.nextToken());

        context.write(word, one);

      }

    }

  }

 

  public static class IntSumReducer

       extends Reducer<Text,IntWritable,Text,IntWritable> {

    private IntWritable result = new IntWritable();

 

    public void reduce(Text key, Iterable<IntWritable> values,

                       Context context

                       ) throws IOException, InterruptedException {

      int sum = 0;

      for (IntWritable val : values) {

        sum += val.get();

      }

      result.set(sum);

      context.write(key, result);

    }

  }

 

  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);

  }

}

 

Mapper

 

我們會接受<key,value>對,hdfs生產map任務對每一個Inputsplit通過Inputformat在我們的作業中。

mapper設定通過Job.setMapperClass(Class) 方法,我們實現mapper介面對應就可以在map中寫內容了。如果向清理內容可以實現cleanUp方法。這個方法 備註  Called once at the end of the task.也就是說在task結束後會觸發一次。

 

輸出對並不一樣要跟輸入對型別保持一致,一個輸入對可能會產生一個或者多個輸出對。輸出通過contextwrite方法收集。

 

應用可以通過Counter 來上報統計,上下文中可以找到Counter counter = context.getCounter(MRJobConfig.JOB_NAME, MRJobConfig.JOB_NAME);

所有的結果通過key來進行發放傳遞給reduce然後落地結果。使用者也可以通過比較器來進行指定分組。

Job.setGroupingComparatorClass(Class).

mapper的輸出會分割槽到reduce中,然後數量與reduce的任務數量一致,也可以通過實現自定義Partitioner來進行分配。

 

combiner也是中間優化的一部分,通過ob.setCombinerClass(Class) 來設定combiner類,在傳送到reduce之前在減少數量從而提高效能。資料結果如何儲存什麼格式,可以通過設定壓縮形式來儲存通過配置。

 

多少個Mapper

mapper的個數通常是通過輸入檔案大小block數量來決定的。正常的並行度水平對於每個結點來看是10-100之間,離線跑hql指令碼一般設定過大會導致佔用資源過多,其他任務排隊情況導致任務從而延遲,或者浪費資源。例子:如果你的輸入檔案大小是10T,那麼hdfs預設塊是128M,那麼你就會有82,000map數量,這個就需要通過配置檔案來設定map 的大小了。

 

Reducer

 

通過mapper處理完以後傳送到reduce端的對,reducer會對這些對再進行處理使得這個以key為分組的對集合更小。

Job.setNumReduceTasks(int) 設定recude個數Job.setReducerClass(Class) 設定reduce的執行類

reduce有三個階段:shuffle, sort and reduce.翻譯出來感覺不太好。

Shuffle

 

這個階段就是通過mapper的輸出結果資料進行一次分組partition

 

Sort

怎麼排序呢,就是mapper階段的task,輸出會是以key分組的,然後相同的key再進行merge 合併排序,在這個階段。

 

Secondary Sort

二次排序,可能使用者對於之前的key排序不滿了,希望再次修改進行重新排序分組那麼通過設定Job.setSortComparatorClass(Class).Job.setGroupingComparatorClass(Class)以達到目的。

 

Reduce

最後一個階段reduce,減少?這麼翻譯總感覺不夠精準那就直接叫reduce吧。以key分組到達一個reduce,拿到資料Context.write(WritableComparable, Writable)寫到檔案系統搞定完畢。reduce的輸出是沒有排序的。

 

多少個reduce

一個合理的數量應該是0.95或者是1.75 乘以 結點數量 * 每個結點最大的容量數。

0.95啟動更快,1.75負載更好。reduce數量多了對叢集是個開銷,但是對於提升成功率更好。因子小於整數的目的也是為了能夠留有餘地。

 

Reducer NONE

reducer設定為空的或者0都可以的。有些任務不要進行對map結果進行排序等操作,就可以直接寫入到檔案系統。FileOutputFormat.setOutputPath(Job, Path)

 

Partitioner

分割槽以key為主鍵,對map結果partiton,按照雜湊的函式方式,數量與reduce任務一樣。

https://hadoop.apache.org/docs/r3.3.0/api/org/apache/hadoop/mapreduce/lib/partition/HashPartitioner.html HashPartitioner是預設的雜湊分割槽方式。

Counter

一個統計工具,上文也說過了,可以通過上下文拿到。

 

 

Task Execution & Environment

 

任務的執行和環境,MRAppMaster執行 mr任務的時候 map reduce都是作為一個程式在一個分開的jvm中執行。

然後我們可以通過配置設定一些jvm的引數,堆疊大小,gc日誌,這些我們可以觀察到任務的執行情況等。

 

 

 

 

Job Submission and Monitoring

 

任務提交和監控說一下,步驟:

1、輸入輸出檢查

2、計算輸入檔案大小

3、設定分散式快取資訊如果有必要

4、然後就是上傳jar 和配置 到mr 的執行目錄下

5、提交到ResourceManager上然後監控它的狀態

 

Job.submit() : 作業提交到叢集立即返回.

Job.waitForCompletion(boolean) : 作業提交到叢集然後等待完成

 

 

  Memory Management Map Parameters Shuffle/Reduce Parameters Configured Parameters不介紹上了,主要是mr的執行原理說一下,剩下的可以通過開頭的mr連線瞭解到,官網這一篇還是有很多東西的,後面沒有說到的輸入輸出檔案類,split類,分散式快取,提交debug指令碼檢視日誌等等,大家都可以去看一下,最後是個wordcount案例應用了這些特點。

  看到的小夥伴有什麼工作機會可以跟我聯絡目前在考慮新機會,多謝!

 

            Growth depends on cycles

相關文章