MapReduce中常用组件
Mapper :map阶段核心处理逻辑
Reducer : reducer阶段核心逻辑处理
MR 程序必须指定一个输入目录,一个输出目录
InputFormat 输入格式
-
FileInputFormat :普通文件
-
DBInputFormat : 处理数据库中的数据
-
SequnceFileInputFileFormat :SequeceFile (hadoop提供的一种文件格式)
RecodeReader: 记录读取器,负责从输入格式中读取数据,读取后封装为一组k,v记录
OutPutFormat 输出格式
- FileOutputFormat : 写入普通文件
- DBOutputForamt : 写入数据库
- SequnceFileOutPutFileFormat : 写入到SequnceFile
RecideWriter : 记录写出器,负责将处理的结果以什么样的格式写出到输出文件中。
Partitioner : 分区器,负责在Mapper将数据写出时,为每组keyout-valueout打上标记,进行分区!目的: 一个ReduceTask只会处理一个分区的数据!
MR中数据流程
- InputFormat调用RecordReader,从输入目录的文件中,读取一组数据,封装为keyin-valuein对象
- 将封装好的key-value,交给Mapper.map()------>将处理的结果写出 keyout-valueout
- ReduceTask启动Reducer,使用Reducer.reduce()处理Mapper写出的keyout-valueout
- OutPutFormat调用RecordWriter,将Reducer处理后的keyout-valueout写出到文件
案例演示流程
通过字母统计案例 计算文本中a-z 出现的频率,将a-p、q-z的结果分别放到一个2个文件中
# 文本1 a.txt
a,b,c
a,w,z
w,p,b
# 文本2 b.txt
z,w,a
# 结果
# 输出文本1
a 3
b 2
c 1
# 输出结果2
p 1
w 3
z 2
-
Map阶段:运行MapTask,将一个任务切分为若干小任务,处理输出阶段性的结果
切片数据(切分数据,默认切分策略根据block块大小切分)
例如上述文本分存在下面2个文本中
a.txt 200m b.txt 100m
切分后数据 3片(份)
a.txt (0m-128m) (128m-200m)
b,txt (0m-100m) -
运行MapTask(进程),每个MapTask负责一片数据(3片数据3个MapTask任务并行执行)
-
读取数据阶段
在MR中,所有数据必须封装为key-value
在MR中,所有的数据必须封装为key-value
MapTask1,2,3都会初始化一个InputFormat(默认TextInputFormat),每个InputFormat对象负责创建一个RecordReader(LineRecordReader)对象,RecordReader负责从每个切片的数据中读取数据,封装为key-value.
LineRecordReader: 将文件中的每一行封装为一个key(offset)-value(当前行的内容)a,b,c -> (0 , (a,b,c))
a,w,z -> (10 , (a,w,z))
w,p,b -> (20, (w,p,b)) -
进入Mapper的map()阶段
map()是Map阶段的核心处理逻辑! 单词统计! map()会循环调用,对输入的每个Key-value都进行处理!输入 :(0 , (a,b,c))
输出 :(a 1) (b 1) (c 1)
… … -
目前,我们需要启动两个ReduceTask,生成两个结果文件,需要将MapTask输出的记录进行分区(分组,分类)
在Mapper输出后,调用Partitioner,对Mapper输出的key-value进行分区,分区后也会排序(默认字典顺序排序)MapTask1
0号区 : (a 1) (a 1) (b 1)(c 1)
1号区 : (w 1) (z 1)MapTask2
0号区 : (b 1)
1号区 : (w 1) (p 1)MapTask3
0号区 : (a 1)
1号区 : (w 1) (z 1) -
Reduce 阶段1
copy:ReduceTask启动后,会启动shuffle线程,从MapTask中拷贝相应分区的数据
ReduceTask1 :只负责0号分区 (a 1) (a 1) (b 1) (c 1) (b 1) (w 1) (p 1)
ReduceTask2 :只负责1号分区 (w 1) (z 1) (w 1) (p 1) (w 1) (z 1)
-
Reduce 阶段2
sort : 对拉取的数据进行默认字典序排序
ReduceTask1 : (a 1) (a 1) (b 1) (b 1) (c 1) (w 1) (p 1)
ReduceTask2 :只负责1号分区 (w 1) (w 1) (w 1) (p 1) (z 1) (z 1)
-
Reduce 阶段3
ReduceTask1 调用 Reducer 的 reduce 方法
进行计算:一次读入一组数据 相同key为一组
输入:(a 1) (a 1)
输出:(a 2)
… … -
调用OutPutFormat中的RecordWriter将Reducer输出的记录写出
ReduceTask1 调用 OutPutFormat(默认TextOutPutFormat)调用 RecordWriter(LineRecoreWriter)
LineRecoreWriter将一个key-value以一行写出 自定义空格分隔
在输出目录中,生成文件part-r-0000
a 3
b 2
c 1ReduceTask2 同样调用 OutPutFormat(默认TextOutPutFormat)调用 ecordWriter(LineRecoreWriter)
在输出目录中,生成文件part-r-0001
p 1
w 3
z 2
总结
Map阶段(MapTask): 切片(Split)-----读取数据(Read)-------交给Mapper处理(Map)------分区和排序(sort)
Reduce阶段(ReduceTask): 拷贝数据(copy)------排序(sort)-----合并(reduce)-----写出(write)