MR核心程式設計思想總結

大資料面壁者發表於2020-11-19

MR核心程式設計思想總結

一、MR思想初識

先分後合思想,MR程式分為map和ruduce兩個階段,map階段負責將海量資料分類形成kv鍵值對,reduce階段負責將map階段形成的kv鍵值對分組合並。

1、首先待計算的資料在client端生成切片(邏輯上對資料進行劃分) , 生成的切片個數對應著要啟動多少個MapTask程式進行Map階段的計算.      
2、多個MapTask程式是並行執行的,互不相干. 
3、在每個MapTask中對資料的處理要考慮到很多細節, 是否有分割槽, 如何排序, 資料如何寫磁碟等..
4、多個MapTask計算完成後,每個MapTask都會有輸出的資料
5、會根據分割槽的個數決定啟動多少個ReduceTask(邏輯上來說), 實際上是 啟動多少個ReduceTask就會生成多少個分割槽.       
6、每個ReduceTask會到每個MapTask中拷貝自己所要處理的資料,說白了就是對應的分割槽的資料.
7、每個ReduceTask最終也會輸出最後的結果.

程式碼案例詳見:手寫MR程式之wordcount案例https://blog.csdn.net/weixin_42796403/article/details/109749080

MR核心思想詳見:MapReduce核心思想https://blog.csdn.net/weixin_42796403/article/details/109732859

二、MR程式組成

一個完整的MR程式在分散式執行時有三類例項程式執行
1、MrAppMaster:負責整個程式執行過程的排程和狀態協調
–MrAppMaster可以理解為是ApplicationMaster的具體實現類,每執行一個mr程式,就會生成一個 MrAppMaster物件,負責監控MR程式的執行過程
2、MapTask:負責Map階段的整個資料處理流程
3、ReduceTask:負責Reduce階段的整個資料處理流程

通過官方wordcount案例分析:
編寫一個可執行的MR程式,需要3部分:
1、自定義mapper(需繼承Mapper父類,重寫map()方法)
public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {} --父類
四個泛型: 兩組kv對
輸入資料的kv型別:
–KEYIN : LongWritable 表示檔案讀取資料的偏移量,簡單理解為每次從檔案的哪個位置開始讀取資料.
–VALUEIN : Text 實際從檔案中讀取的一行資料
輸出資料的kv型別:
–KEYOUT : Text 表示一個單詞
–VALUEOUT : IntWritable 表示這個單詞出現了1次.

2、自定義reducer(需繼承Reducer父類,重寫reduce()方法)
public class Reducer<KEYIN,VALUEIN,KEYOUT,VALUEOUT> {} --父類
四個泛型: 兩組kv對
輸入資料的kv型別: Reducer輸入資料的kv型別要對應Mapper輸出資料的kv型別
–KEYIN : Text 表示一個單詞
–VALUEIN : IntWritable 表示該單詞出現了1次
輸出資料的kv型別:
–KEYOUT : Text 表示一個單詞
–VALUEOUT: IntWritable 表示該單詞總共出現的次數

3、驅動類Driver
在Driver類中需指定MR執行的環境、Map和Reduce執行類、輸入輸出型別、輸入輸出路徑、分割槽、是否聚集等資訊。
將我們寫好的Mapper和Reducer打包成一個Job,可以提交到本地或者是Yarn上執行

三、MR程式內部方法剖析

/*
Mapper類
	1、 所有的MapReduce程式中的自定義Mapper類都需要繼承Mapper類.
    2、 setup(): 在MapTask開始執行時呼叫1次.
    3、 map()  : 為輸入資料的每個kv都呼叫一次map方法.大部分的MapReduce程式都需要重寫該方法.
    4、 cleanup(): 在MapTask結束前呼叫1次
    5、 run()方法: 控制Mapper中的 setup  map  cleanup執行的方法
*/       
	public void run(Context context) throws IOException, InterruptedException {
         setup(context);  // setup方法執行了一次
         try {
             while (context.nextKeyValue()) {  //判斷是否還有下一個輸入的kv
             // 執行map方法,傳入當前key  當前value
             map(context.getCurrentKey(), context.getCurrentValue(), context);
         }
         } finally {
           cleanup(context);  // cleanup方法執行了一次
         }
        }

/*
Reducer類
    1、 所有的MapReduce程式中的自定義Reducer類都需要繼承Reducer類.
	2、 setup():在ReduceTask開始執行時呼叫1次
	3、 reduce(): 為每個key呼叫1次reduce方法,大部分的MapReduce程式都需要重寫該方法. 
	    map寫出的N個kv,其中會有很多相同的k, 在進入到reduce方法前,會按照k進行分組,把相同k的多個kv對		分成一個組中. 一組的資料會執行一次reduce方法.
	4、 cleanup(): 在ReduceTask結束前呼叫1次
	5、 run():  控制Reducer中的 setup  reduce  cleanup執行的方法
*/
	
	 public void run(Context context) throws IOException, InterruptedException {
          setup(context);  //呼叫1次setup方法
          try {
               while (context.nextKey()) {  //是否有下個key
	           //執行reduce方法,輸入當前key和values
                   reduce(context.getCurrentKey(), context.getValues(), context);
                   // If a back up store is used, reset it
                   Iterator<VALUEIN> iter = context.getValues().iterator();
                   if(iter instanceof ReduceContext.ValueIterator) {
                   ((ReduceContext.ValueIterator<VALUEIN>)iter).resetBackupStore();       
          }
         }
           } finally {
              cleanup(context);  //呼叫1次cleanup方法
           }
         }

相關文章