本文原始碼:GitHub·點這裡 || GitEE·點這裡
一、MapReduce概述
1、基本概念
Hadoop核心元件之一:分散式計算的方案MapReduce,是一種程式設計模型,用於大規模資料集的並行運算,其中Map(對映)和Reduce(歸約)。
MapReduce既是一個程式設計模型,也是一個計算元件,處理的過程分為兩個階段,Map階段:負責把任務分解為多個小任務,Reduce負責把多個小任務的處理結果進行彙總。其中Map階段主要輸入是一對Key-Value,經過map計算後輸出一對Key-Value值;然後將相同Key合併,形成Key-Value集合;再將這個Key-Value集合轉入Reduce階段,經過計算輸出最終Key-Value結果集。
2、特點描述
MapReduce可以實現基於上千臺伺服器併發工作,提供很強大的資料處理能力,如果其中單臺服務掛掉,計算任務會自動轉義到另外節點執行,保證高容錯性;但是MapReduce不適應於實時計算與流式計算,計算的資料是靜態的。
二、操作案例
1、流程描述
資料檔案一般以CSV格式居多,資料行通常以空格分隔,這裡需要考慮資料內容特點;
檔案經過切片分配在不同的MapTask任務中併發執行;
MapTask任務執行完畢之後,執行ReduceTask任務,依賴Map階段的資料;
ReduceTask任務執行完畢後,輸出檔案結果。
2、基礎配置
hadoop:
# 讀取的檔案源
inputPath: hdfs://hop01:9000/hopdir/javaNew.txt
# 該路徑必須是程式執行前不存在的
outputPath: /wordOut
3、Mapper程式
public class WordMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
Text mapKey = new Text();
IntWritable mapValue = new IntWritable(1);
@Override
protected void map (LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
// 1、讀取行
String line = value.toString();
// 2、行內容切割,根據檔案中分隔符
String[] words = line.split(" ");
// 3、儲存
for (String word : words) {
mapKey.set(word);
context.write(mapKey, mapValue);
}
}
}
4、Reducer程式
public class WordReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
int sum ;
IntWritable value = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values,Context context)
throws IOException, InterruptedException {
// 1、累加求和統計
sum = 0;
for (IntWritable count : values) {
sum += count.get();
}
// 2、輸出結果
value.set(sum);
context.write(key,value);
}
}
5、執行程式
@RestController
public class WordWeb {
@Resource
private MapReduceConfig mapReduceConfig ;
@GetMapping("/getWord")
public String getWord () throws IOException, ClassNotFoundException, InterruptedException {
// 宣告配置
Configuration hadoopConfig = new Configuration();
hadoopConfig.set("fs.hdfs.impl",
org.apache.hadoop.hdfs.DistributedFileSystem.class.getName()
);
hadoopConfig.set("fs.file.impl",
org.apache.hadoop.fs.LocalFileSystem.class.getName()
);
Job job = Job.getInstance(hadoopConfig);
// Job執行作業 輸入路徑
FileInputFormat.addInputPath(job, new Path(mapReduceConfig.getInputPath()));
// Job執行作業 輸出路徑
FileOutputFormat.setOutputPath(job, new Path(mapReduceConfig.getOutputPath()));
// 自定義 Mapper和Reducer 兩個階段的任務處理類
job.setMapperClass(WordMapper.class);
job.setReducerClass(WordReducer.class);
// 設定輸出結果的Key和Value的型別
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//執行Job直到完成
job.waitForCompletion(true);
return "success" ;
}
}
6、執行結果檢視
將應用程式打包放到hop01服務上執行;
java -jar map-reduce-case01.jar
三、案例分析
1、資料型別
Java資料型別與對應的Hadoop資料序列化型別;
Java型別 | Writable型別 | Java型別 | Writable型別 |
---|---|---|---|
String | Text | float | FloatWritable |
int | IntWritable | long | LongWritable |
boolean | BooleanWritable | double | DoubleWritable |
byte | ByteWritable | array | DoubleWritable |
map | MapWritable |
2、核心模組
Mapper模組:處理輸入的資料,業務邏輯在map()方法中完成,輸出的資料也是KV格式;
Reducer模組:處理Map程式輸出的KV資料,業務邏輯在reduce()方法中;
Driver模組:將程式提交到yarn進行排程,提交封裝了執行引數的job物件;
四、序列化操作
1、序列化簡介
序列化:將記憶體中物件轉換為二進位制的位元組序列,可以通過輸出流持久化儲存或者網路傳輸;
反序列化:接收輸入位元組流或者讀取磁碟持久化的資料,載入到記憶體的物件過程;
Hadoop序列化相關介面:Writable實現的序列化機制、Comparable管理Key的排序問題;
2、案例實現
案例描述:讀取檔案,並對檔案相同的行做資料累加計算,輸出計算結果;該案例演示在本地執行,不把Jar包上傳的hadoop伺服器,驅動配置一致。
實體物件屬性
public class AddEntity implements Writable {
private long addNum01;
private long addNum02;
private long resNum;
// 構造方法
public AddEntity() {
super();
}
public AddEntity(long addNum01, long addNum02) {
super();
this.addNum01 = addNum01;
this.addNum02 = addNum02;
this.resNum = addNum01 + addNum02;
}
// 序列化
@Override
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeLong(addNum01);
dataOutput.writeLong(addNum02);
dataOutput.writeLong(resNum);
}
// 反序列化
@Override
public void readFields(DataInput dataInput) throws IOException {
// 注意:反序列化順序和寫序列化順序一致
this.addNum01 = dataInput.readLong();
this.addNum02 = dataInput.readLong();
this.resNum = dataInput.readLong();
}
// 省略Get和Set方法
}
Mapper機制
public class AddMapper extends Mapper<LongWritable, Text, Text, AddEntity> {
Text myKey = new Text();
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
// 讀取行
String line = value.toString();
// 行內容切割
String[] lineArr = line.split(",");
// 內容格式處理
String lineNum = lineArr[0];
long addNum01 = Long.parseLong(lineArr[1]);
long addNum02 = Long.parseLong(lineArr[2]);
myKey.set(lineNum);
AddEntity myValue = new AddEntity(addNum01,addNum02);
// 輸出
context.write(myKey, myValue);
}
}
Reducer機制
public class AddReducer extends Reducer<Text, AddEntity, Text, AddEntity> {
@Override
protected void reduce(Text key, Iterable<AddEntity> values, Context context)
throws IOException, InterruptedException {
long addNum01Sum = 0;
long addNum02Sum = 0;
// 處理Key相同
for (AddEntity addEntity : values) {
addNum01Sum += addEntity.getAddNum01();
addNum02Sum += addEntity.getAddNum02();
}
// 最終輸出
AddEntity addRes = new AddEntity(addNum01Sum, addNum02Sum);
context.write(key, addRes);
}
}
案例最終結果:
五、原始碼地址
GitHub·地址
https://github.com/cicadasmile/big-data-parent
GitEE·地址
https://gitee.com/cicadasmile/big-data-parent
推薦閱讀:程式設計體系整理
序號 | 專案名稱 | GitHub地址 | GitEE地址 | 推薦指數 |
---|---|---|---|---|
01 | Java描述設計模式,演算法,資料結構 | GitHub·點這裡 | GitEE·點這裡 | ☆☆☆☆☆ |
02 | Java基礎、併發、物件導向、Web開發 | GitHub·點這裡 | GitEE·點這裡 | ☆☆☆☆ |
03 | SpringCloud微服務基礎元件案例詳解 | GitHub·點這裡 | GitEE·點這裡 | ☆☆☆ |
04 | SpringCloud微服務架構實戰綜合案例 | GitHub·點這裡 | GitEE·點這裡 | ☆☆☆☆☆ |
05 | SpringBoot框架基礎應用入門到進階 | GitHub·點這裡 | GitEE·點這裡 | ☆☆☆☆ |
06 | SpringBoot框架整合開發常用中介軟體 | GitHub·點這裡 | GitEE·點這裡 | ☆☆☆☆☆ |
07 | 資料管理、分散式、架構設計基礎案例 | GitHub·點這裡 | GitEE·點這裡 | ☆☆☆☆☆ |
08 | 大資料系列、儲存、元件、計算等框架 | GitHub·點這裡 | GitEE·點這裡 | ☆☆☆☆☆ |