MapReduce原理

1. MapReduce核心思想

image-20230412092434701

image-20230412092511177

1.1 分而治之

  • 把一个复杂的问题,按照一定分解的方法,分为等价的规模较小的若干部分,然后逐个解决,分别找出个部分的结果,把各部分的结果组成整个问题的结果。

1.2 总结与思考⭐

1)MR的核心思想,分而治之,把一个复杂的问题,按照一定分解的方法,分为等价的规模较小的若干部分,然后逐个解决,分别找出个部分的结果,把各部分的结果组成整个问题的结果

2. MapReduce

image-20230412093056975

image-20230412093114711

2.1 Map阶段

  • 将任务分解,把复杂任务分解成若干简单的任务,并行处理,前提是这些任务没有必然的依赖关系,可以单独执行任务

2.2 Reduce阶段

  • 负责将任务合并,把map阶段的结果进行全局汇总

2.3 总结与思考⭐

1)MR程序分为Map-Shffule-Reduce阶段,Map任务分解,Shffule洗牌排序,Reduce任务合并

3. MapReduce编程模型

image-20230412093305031

3.1 键值对转换

  • 整个mapreduce的过程就是整个键值对转换的过程

image-20230412093343072

image-20230412093510953

image-20230412093547311

3.2 多个MapReduce任务

image-20230412093852669

3.3 总结与思考⭐

1)MR编程模型,用于处理大规模并行计算(MPP)

2)MR数据流模型

image-20230517092701315

3)MR可能不需要Reduce任务

4. MapReduce编程实例

4.1 词频统计

image-20230412094522045

## k1 v1
<0,Hello World>
<12,Hello Hadoop>
## 0,12表示偏移里量

## k2 v2
<Hello 1>
<World 1>
## 1,1表示数据量

##k3 v3
<hadoop 2>
<hello 3>
##2,3表示数据统计量

## 整个mapreduce的过程就是整个键值对的转换

4.2 总结与思考⭐

1)文件内容--TextInputFormat--><k1,v1>--MAP--><k2,v2>--shffule洗牌-Reduce-><k3,v3>

5. MapReduce工作过程⭐⭐⭐⭐⭐

image-20230412094658751

image-20230517104854320

5.1 分片 / 格式化数据源

image-20230412094735201

## 1. 将源文件进行拆分成分片(split),拆分成(Hadoop2.x 默认是128M),每一个分片(split)就是一个map任务,每一个map任务都会执行一个map函数,map函数处理分片里的每一条记录;
## 2. 将划分好的分片(split)格式化成键值对,key代表偏移量,value代表每一行内容

5.2 执行MapTask

image-20230412095247598

## 1. 每个map任务都有一个内存缓冲区(缓冲区大小100M)
## 2. 经过map任务处理的中间结果会进入缓冲区
## 3. 如果写入的数据达到阀值(80M),则会启动一个线程将内存溢出的数据写入磁盘(剩下20M留给中间结果继续写入)
## 4. 溢写过程中,MapReduce框架会对Key进行排序
## 5. 中间结果较大,会形成多个溢写文件,最后缓冲区数据也会全部溢写如磁盘形成一个溢写文件
## 6. 如果是多个溢写文件,最后会合并成一个文件

5.3 执行shuffle过程

image-20230412101448581

## map阶段数据传递给reduce阶段,这个过程叫做shuffle
## shuffle会将mapTask输出的处理结果数据,分发给reduceTask,并在分发过程中,对数据按key进行分区和排序

image-20230517095548967

5.4 执行ReduceTask

image-20230412101727196

## 输入ReduceTask的数据流是<key,{value list}>
## reduce()方法进行逻辑处理,再以<key,value>的形式输出

5.5 写入文件

image-20230412101921234

## MapReduce框架会将RedcueTask生成的<key,value>传入OutoutFormat的write方法中,实现文件的写入

image-20230412102126508

## 一般情况下,一个block(物理分片)对应一个split(逻辑分片),一个split(分片)对应一个maptask
## 每一个split会格式化为<k1,v1>的键值对
## <k1,v1>经过mapTask转换为<k2,v2>
## <k2,v2>经过shuffle(Group)转换为<k2,{v2,.....}>
## <k2,{v2,.....}>经过Reduce转换为<k3,v3>

5.6 总结与思考⭐

MR工作过程;参考图片:/home/fubo/OneDrive/笔记/理论知识⭐/大数据原理/离线批处理/34247528fa3340968c5fa58d73b31b34.png

1)分片 / 格式化数据源;拆分为split(默认128M),一个split对应一个map;格式化split,生成<k1,v1>,key代表偏移量,value代表每一行内容

2)执行MAPTASK;MAP任务会对SPLIT进行加工处理,生成<k2,v2>

3)Shuffle阶段(溢写,归并);对<k2,v2>进行排序,文件的拆分合并;参考⭐⭐:https://blog.csdn.net/weixin_42322454/article/details/128400205

将结果存入内存缓冲区(默认100M)中,超过阈值(80M)或完成计算,会溢写成一个文件,溢写的过程会对key进行排序,并对溢写的进行拆分合并(合并排序,一是分区内的合并同分区,并排序;二是不同溢写文件的,合并文件并排序),所以这个过程可能会因为key值发生数据倾斜

4)执行ReduceTask;将<k2,v2>转换为<k3,v3>

5)写入文件;将<k3,v3>传入OutPutFormat的write方法

6)整体路程参考下图

image-20230517104854320

6. MapTask工作原理⭐⭐⭐⭐⭐

image-20230412103132684

6.1 Read阶段

image-20230412103216839

## read阶段:MapTask通过用户编写的RecordReader,从输入的InputSplit中解析出一个个key/value(即<k1,v1>)
## 一般情况下,会把一行数据转换成一个键值对

6.2 Map阶段

image-20230412103405484

## map阶段:将解析出的key/value交给用户编写的map()函数处理,并产生一系列新的键值对即(<k2,v2>)

6.3 Collect阶段(shffule)

image-20230412103710234

## collect阶段:在用户编写的map()函数中,数据处理完成后,会调用outputCollector.coolect()输出结果
## outputCollector.coolect()函数会将<k2,v2>(通过调用partitioner),写入一个环形内存缓冲区(默认100M)

6.4 Spill阶段(shffule)

image-20230412104123071

## Spill阶段:溢写阶段,环形缓冲区达到80M后,MapReduce会将数据写到本地磁盘上,生成一个临时文件
## 写入本地磁盘前,会对数据进行一次本地排序,并在必要时对数据进行合并/压缩

6.5 Combine阶段(shffule)

image-20230412104453742

## Conbie阶段:当所有处理完成后,mapTask对所有临时文件进行一次合并,确保最终只生成一个数据文件

6.6 总结与思考⭐

1)READ阶段;读取split

2)map阶段;<k1,v1>转换为<k2,v2>

3)Collect/Spill/Combine(map阶段的shuffle);参考⭐⭐:https://blog.csdn.net/weixin_42322454/article/details/128400205

7. ReduceTask工作原理⭐⭐⭐⭐⭐

image-20230412105158327

image-20230412105209496

7.1 Copy阶段(shffule)

image-20230412105237285

## Copy阶段:Reduce会从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阀值,则写到磁盘上,否则直接放入内存中

7.2 Merge阶段(shffule)

image-20230412105539700

## Merge阶段:在远程拷贝数据的同时,ReduceTask会启动两个后台线程,分别对内存和磁盘上的文件进行合并,以防止内存使用过多或者磁盘文件过多

7.3 Sort阶段(shffule)

image-20230412105911390

## 用户编写reduce()方法输入数据是按key进行聚集的一组数据。
## 为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。
## 由于各个MapTask已经实现对自己的处理结果进行局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可。

7.4 Reduce阶段

image-20230412110653205

## Reduce阶段:对排序后的键值对调用reduce()方法,键相等的键值对调用一次reduce()方法
## 每次调用会产生0个或者多个键值对
## 最后把输出的键值对写入到HDFS系统中

7.5 Write阶段

image-20230412110957897

## Write阶段:reduce()函数将计算结果写到HDFS上

image-20230412111634351

## 1. copy阶段,将map结果拉取到memoryBuffer(缓存)中,然后对这些数据进行合并
## 2. 超过内存一定阀值时,则会写入到磁盘,也会对磁盘上的文件作一些合并
## 3. 对内存和磁盘中的文件再做一次合并,合并时会作一次排序
## 4. 再将排序后的数据交给ReduceTask
## 5. ReduceTask将结果输出写入到hdfs文件上

7.6 总结与思考⭐

1)Copy/Merge/Sort(reduce阶段的shuffle);数据的拉取,合并,排序;参考⭐⭐:https://blog.csdn.net/weixin_42322454/article/details/128400205

2)Reduce阶段,将<k2,v2>转换为<k3,v3>

3)Write阶段,将结果<k3,v3>写入到HDFS上

8. Shuffle工作原理⭐⭐⭐⭐⭐

image-20230412135848519

8.1 Map阶段的Shuffle

image-20230412135933122

## 1. MapTask处理的结果会放入缓冲区中(该缓冲区默认大小为100M),当缓冲区要溢出时(默认达到缓冲区80%),会在本地文件系统创建一个溢出文件,将该缓冲区的数据写入到这个文件
## 2. 写入磁盘之前,线程会根据reduceTask数量,对数据分区,一个reduce任务对应一个分区的数据。这样做是为了避免有些reduce任务分配到大量数据,而有些reduce任务分到很少的数据(数据倾斜)
## 3. 数据分区,即给<k2,v2>的键值对打上标记
## 4. 分完数据后,会对每个分区的数据进行排序,如果设置了Combiner,将排序后的结果进行combiner操作
## 5. 在map任务输出最有一个记录时,可能有很多溢出小文件,需要对溢出的小文件进行合并,合并的过程中,会进行排序和combine操作
## 6. 其目的有两个:一是尽量减少每次写入磁盘的数据量;二是尽量减少下一复制阶段网络传输的数据量。最后合并成一个已分区且已排序的文件
## 7. 将分区中的数据拷贝给对应(分区的标记)的reduce任务


## 1. mapTask任务结果---》缓存区---》多的溢出到文件
## 2. 线程进行数据分区(给每一个分区打上标记,分到对应的ReduceTask) 排序 合并
## 3. 最后合并成一个已分区且已排序的文件

8.2 Reduce阶段的Shuffle

image-20230412141830261

## 1. Reduce任务接受到不同map任务传来的数据,并且每个map传来的数据都是有序的。
## 2. 如果reduce任务接收的数据量相当小,则直接存储到内存中,如果数据量超过了该缓冲区大小的比例,则对数据合并后溢写到磁盘中
## 3. 随着溢写文件增多,后台线程会将它们合并成一个更大有序的文件,给后面的合并节省了时间
## 4. 合并的过程会产生许多中间文件,但MapReduce会让写入磁盘的数据尽可能的少,并且最后一次合并的结果并没有写入磁盘,而是直接输入到reduce函数

## 1. 拉取mapTask结果
## 2. 合并 排序 输出

8.3 总结与思考⭐

1)Shuffle的重要性:是mapreduce的核心,其性能直接决定MR的性能;参考⭐⭐:https://blog.csdn.net/weixin_42322454/article/details/128400205

2)MAP阶段的Shffule

image-20230517104919237

3)Reduce阶段的Shffule

image-20230517104950138

9. MapReduce的编程组件⭐⭐⭐⭐⭐

image-20230412142608752

9.1 InputFormat组件

image-20230412142723642

image-20230412143052766

InputFormat组件的两个功能
1. 数据切分,切分成若干split,每个split对应一个mapTask    ---->    getSplits方法
2. 数据格式化,将split解析成键值对<k1,v1>                ---->    createRecordReader方法

image-20230412143212647

image-20230412143406143

image-20230412143642811

image-20230412143705806
image-20230412143912318

long splitSize = computeSplitSize(blockSize, minSzie, maxSize)
    
protected long computeSplitSize(long blockSize , long minSize, long maxSize){
    return Math.max(minSize, Math.min(maxSize, blockSize));
}

9.2 Maper组件

image-20230412144335464

image-20230412144509534

9.3 Reducer组件

image-20230412145649852

image-20230412145715748

image-20230412145741848

image-20230412145803620

image-20230412145835504

image-20230412150116425

key  --> k2 --> "hello"
value --> {v2,....} --> "1,1"

9.4 Partitioner组件

image-20230412150615370

image-20230412150626942

image-20230412150650646

int ---分区编号
key --- k1
value --- v1
numPartitions -- reduce任务数

image-20230412151517938

HashPartitioner

image-20230412151712392

key相同,就会被分到同一个reduce任务
分区的目的,是希望map结果能均匀分配到reduce任务中,避免数据倾斜

9.5 Combiner组件

image-20230412152704874

Combiner组件其实就是继承的reduce类
reduce是对整体的计算结果作整体的汇总
而Combiner则是对局部结果作一次汇总

image-20230412152907594

image-20230412152954687

image-20230412153039267

Combiner组件从某种程度上,是对mapreduce任务的优化,有没有输出结果都一样

9.6 OutputFormat组件

image-20230412153255758

image-20230412153444588

常用的:TextOutputFormat<K,V>

9.7 总结与思考⭐

1)InputFormat组件:将文件拆分为split,并格式化为<k1,v1>;split大小由minzise,maxsize,blocksize共同决定

2)Maper组件:map方法对应map任务

3)Reduce组件:reduce方法对应reduce任务,整体的计算结果的汇总

4)Partitioner组件:在map-shffule阶段开始,给<k2,v2>添加分区,之后根据分区分配到不同的reudce任务中

5)Combiner组件:对局部数据的汇总,是对reduce类的重写

6)OutputFormat组件:将结果写入HDFS


10. MapReduce的运行模式

image-20230412153627893

image-20230412153727653

10.1 本地模式

wordcount代码,本地建立input数据源,output文件夹
直接运行WordCountDrive代码即可

image-20230412153945253

image-20230412154003308

image-20230412154020452

image-20230412154119563

10.2 集群运行模式

image-20230412154627171

上面的本地路径要修改为HDFS路径

10.3 总结与思考⭐

1)集群运行模式:将MR程序编译成jar包提交至Yarn集群,Yarn进行资源管理和调度,将程序分发到不同节点并执行,处理的数据结果都在HDFS文件系统中


11. MapReduce性能优化策略

image-20230412154756474

11.1 数据输入

image-20230412154840190

使用CombineTextInputFormat作为输入,解决输入端大量小文件的场景

11.2 Map阶段

image-20230412155102195

## 通过设置以下两个参数,减少spill溢写次数,从而减少磁盘IO
io.sort.mb  --> 环形缓冲区大小,默认100M
sort.spill.percent --> 环形缓冲区溢写的比例,默认80%
## 增大merge的文件数目
io.sort.factor  --> 增大merge的文件数目,减少merge次数,默认是10个
## 加入combine处理
min.num.spill.for.combine 运行combiner时,所需的最少溢出文件数,默认3

image-20230412155538215

image-20230412155552831

11.3 Reduce阶段

image-20230412155753615

image-20230412160007566

11.4 Shuffle阶段

image-20230412160151068

11.5 其他属性调优

image-20230412160335194

image-20230412160357798

image-2023041217152197411.6 总结与思考⭐

1)数据输入阶段:将小文件合并,减少map任务数量,使用CombineTextInputFormat输入

2)Map阶段:减少spill(io.sort.mb,sort.spill.percent),merge次数(io.sort.factor),进行combine处理(min.num.spill.for.combine);

image-20230517112151109

3)Reduce阶段:合理设置reduce/map任务数量;设置map/reduce共存;规避reduce;设置reduce的buffer

image-20230517112356375

4)Shuffle阶段:给Shuffle提供更多的内存空间

image-20230517112448557

5)其他属性调优

image-20230517112537596


12.经典案例

12.1 MapReduce经典案例-倒排索引(待学习)

image-20230412160551868

倒排索引是文档检索系统中最常用的数据结构,被广泛应用于全文搜索引擎。
倒排索引主要用来存储某个单词(或词组)在一组文档中的存储位置的映射,提供了可以根据内容来查找文档的方式,而不是根据文档来确定内容,因此称为倒排索引。
带有倒排索引的文件,我们称为倒排索引文件,简称为倒排文件

image-20230412161108429

image-20230412161204299

image-20230412161239719

image-20230412161325744

image-20230412161344517

image-20230412161528431

image-20230412161622652

image-20230412161744095

image-20230412161820116

image-20230412170317703

image-20230412170414585

image-20230412170510212

image-20230412170602358

image-20230412171004076

12.2 MapReduce经典案例-数据去重(待学习)

12.3 MapReduce经典案例-TopN(待学习)

posted @ 2023-06-28 16:18  付十一。  阅读(155)  评论(0)    收藏  举报