mapreducer--2

Wirtable Comparable 排序
MapTask和ReduceTask均會對數據key進行排序。
默認是按照字典排序,實現方法是快速排序
在這裏插入圖片描述
2.排序的分類
在這裏插入圖片描述
compareto 是兩個條件就是二次排序,3個條件就是三次排序。
2.自定義排序WritableComparable
(1)原理分析
bean對象做爲key傳輸,需要實現WritableComparable接口重寫compareTo方法,就可以實現排序。
@Override
public int compareTo(FlowBean o) {
int result;
// 按照總流量大小,倒序排列
if (sumFlow > bean.getSumFlow()) {
result = -1;
}else if (sumFlow < bean.getSumFlow()) {
result = 1;
}else {
result = 0;
}
return result;
}
全排序
在這裏插入圖片描述
Combiner 合併
在這裏插入圖片描述
自定義Combiner實現步驟
(a)自定義一個Combiner繼承Reducer,重寫Reduce方法
public class WordcountCombiner extends Reducer<Text, IntWritable, Text,IntWritable>{
@Override
protected void reduce(Text key, Iterable values,Context context) throws IOException, InterruptedException {

    // 1 彙總操作
	int count = 0;
	for(IntWritable v :values){
		count += v.get();
	}

    // 2 寫出
	context.write(key, new IntWritable(count));
}

}
(b)在Job驅動類中設置:
job.setCombinerClass(WordcountCombiner.class);
GroupingComparator分組(輔助排序)
對Reduce階段的數據根據某一個或幾個字段進行分組。
分組排序步驟:
(1)自定義類繼承WritableComparator
(2)重寫compare()方法
@Override
public int compare(WritableComparable a, WritableComparable b) {
// 比較的業務邏輯
return result;
}
(3)創建一個構造將比較對象的類傳給父類
protected OrderGroupingComparator() {
super(OrderBean.class, true);
}
map Task工作機制
在這裏插入圖片描述
(1)Read階段:MapTask通過用戶編寫的RecordReader,從輸入InputSplit中解析出一個個key/value。
(2)Map階段:該節點主要是將解析出的key/value交給用戶編寫map()函數處理,併產生一系列新的key/value。
(3)Collect收集階段:在用戶編寫map()函數中,當數據處理完成後,一般會調用OutputCollector.collect()輸出結果。在該函數內部,它會將生成的key/value分區(調用Partitioner),並寫入一個環形內存緩衝區中。
(4)Spill階段:即“溢寫”,當環形緩衝區滿後,MapReduce會將數據寫到本地磁盤上,生成一個臨時文件。需要注意的是,將數據寫入本地磁盤之前,先要對數據進行一次本地排序,並在必要時對數據進行合併、壓縮等操作。
溢寫階段詳情:
步驟1:利用快速排序算法對緩存區內的數據進行排序,排序方式是,先按照分區編號Partition進行排序,然後按照key進行排序。這樣,經過排序後,數據以分區爲單位聚集在一起,且同一分區內所有數據按照key有序。
步驟2:按照分區編號由小到大依次將每個分區中的數據寫入任務工作目錄下的臨時文件output/spillN.out(N表示當前溢寫次數)中。如果用戶設置了Combiner,則寫入文件之前,對每個分區中的數據進行一次聚集操作。
步驟3:將分區數據的元信息寫到內存索引數據結構SpillRecord中,其中每個分區的元信息包括在臨時文件中的偏移量、壓縮前數據大小和壓縮後數據大小。如果當前內存索引大小超過1MB,則將內存索引寫到文件output/spillN.out.index中。
(5)Combine階段:當所有數據處理完成後,MapTask對所有臨時文件進行一次合併,以確保最終只會生成一個數據文件。
當所有數據處理完後,MapTask會將所有臨時文件合併成一個大文件,並保存到文件output/file.out中,同時生成相應的索引文件output/file.out.index。
在進行文件合併過程中,MapTask以分區爲單位進行合併。對於某個分區,它將採用多輪遞歸合併的方式。每輪合併io.sort.factor(默認10)個文件,並將產生的文件重新加入待合併列表中,對文件排序後,重複以上過程,直到最終得到一個大文件。
讓每個MapTask最終只生成一個數據文件,可避免同時打開大量文件和同時讀取大量小文件產生的隨機讀取帶來的開銷。
ReduceTask工作機制
在這裏插入圖片描述
(1)Copy階段:ReduceTask從各個MapTask上遠程拷貝一片數據,並針對某一片數據,如果其大小超過一定閾值,則寫到磁盤上,否則直接放到內存中。
(2)Merge階段:在遠程拷貝數據的同時,ReduceTask啓動了兩個後臺線程對內存和磁盤上的文件進行合併,以防止內存使用過多或磁盤上文件過多。
(3)Sort階段:按照MapReduce語義,用戶編寫reduce()函數輸入數據是按key進行聚集的一組數據。爲了將key相同的數據聚在一起,Hadoop採用了基於排序的策略。由於各個MapTask已經實現對自己的處理結果進行了局部排序,因此,ReduceTask只需對所有數據進行一次歸併排序即可。
(4)Reduce階段:reduce()函數將計算結果寫到HDFS上。
在這裏插入圖片描述
Reduce join --join
在這裏插入圖片描述
Map Join
1.使用場景
Map Join適用於一張表十分小、一張表很大的場景。
2.優點
思考:在Reduce端處理過多的表,非常容易產生數據傾斜。怎麼辦?
在Map端緩存多張表,提前處理業務邏輯,這樣增加Map端業務,減少Reduce端數據的壓力,儘可能的減少數據傾斜。
3.具體辦法:採用DistributedCache
(1)在Mapper的setup階段,將文件讀取到緩存集合中。
(2)在驅動函數中加載緩存。
// 緩存普通文件到Task運行節點。
job.addCacheFile(new URI(“file://e:/cache/pd.txt”));在這裏插入圖片描述
計數器應用
在這裏插入圖片描述

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