Hadoop MapReduce工作流程

## MapReduce框架

![image-20201021160744505](https://gitee.com/chenglm/lmpics/raw/master/img/20201021160744.png)

## Block块、切片、MapTask的关系

1. BlockSize在hadoop2.x为128M
2. split切片为逻辑概念,默认SplitSize = BlockSize,也可以自行设置
3. 一个job在Map阶段的并行度由job提交时的切片数量决定
4. 切片时,针对每一个文件单独切片
5. 每一个split切片分配一个MapTask单独处理

## InputFormat

将文件转换为KV值

自定义InputFormat

```java
public class WholeInputFormat extends FileInputFormat<Text, BytesWritable> {
    @Override
    public RecordReader<Text, BytesWritable> createRecordReader(InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException {
        return new WholeFileRecordReader();
    }

    @Override
    protected boolean isSplitable(JobContext context, Path filename) {
        return false;
    }
}
```

```java
public class WholeFileRecordReader extends RecordReader<Text, BytesWritable>{}
//Text为文件名
//BytesWritable为文件
```

## Map

映射,负责数据的过滤分法,将原始数据转化为键值对

## Shuffle

在Map方法之后,Reduce方法之前的过程为Shuffle。

为了让Reduce可以并行处理Map的结果,必须对Map的输出进行一定的排序与分割,然后再交给对应的Reduce,而这个将Map输出进行进一步整理并交给Reduce的过程就是Shuffle。

### Map Shuffle阶段:

1. OutputCollector将Mapper处理好的数据收集起来,向环形缓冲区中输入(一侧存放KV值,另一侧存放索引)。

2. 环形缓冲区的内存达到80%(默认)时,进行分区排序(只移动索引的相应位置),排序后溢写到磁盘上,最终生成一个分区有序的文件

   1. 分区排序为二次排序,使用快排。先对区号进行排序,再对区号内部进行排序。

      1. 区间排序根据key值的hash值进行排序
      2. 区内排序根据key实现的类WritableCompatarable中的CompareTo方法排序

   2. 另外20%内存,依然源源不断地接受数据

   3. 在进行溢写的时候,可以进行Combiner(如<b,1><b,1>就会合并成<b,2>)

      1. 在spill溢写过程中,为了判定某个partition在这个文件中存放的起始位置,有一个三元组记录某个partition对应的数据在这个文件中的索引:起始位置、原始数据长度、压缩之后的数据长度。一个partition对应一个三元组。一个spill文件拥有一个index索引文件

   4. 生成多个溢写文件

   5. 将多个溢写文件进行归并排序,可以进行Combiner

      1. 在本地目录上进行扫描,获取spill文件和index文件
      2. 从索引列表中查询这个partition对应的所有索引信息,每个对应一个段插入到segement列表中。
      3. 对这个partition对应的所有的segment进行归并合并,目标是合并成一个segment。
      4. 将多个segement合并为一个输出文件。

      

### Reduce Shuffle阶段

1. 所有MapTask完成后,启动ReduceTask,通过HTTP向各个MapTask拖取它所需要的数据。
2. 归并排序(可能使用了分组)

## GroupingCompatator

继承了WritableComparator类,能够对Map输入的数据进行分组

## Reduce

Reduce一次读取一组,进行处理

## OutputFormat

## 工作流程

![img](https://gitee.com/chenglm/lmpics/raw/master/img/20201021160026.png)

![img](https://gitee.com/chenglm/lmpics/raw/master/img/20201021160033.png)

1. 在客户端完成对文件的切片
2. 获取信息(Job.split切片的信息、jar包本身、Job.xml配置信息)
3. 提交信息给yarn看
4. 根据Job.split,计算出MapTask数量(一个切片,一个MapTask)
5. (以一个MapTask为例),MapTask生成InputFormat对象,调用RecorderReader(负责把切片切割成KV值)
6. KV值输入给了Mapper的map方法(MapTask拥有InputFormat、Mapper两个对象),处理完的KV值以序列化的方式,被OutputCollector收集
7. 序列化的kv值存放在环形缓存中。环形缓冲区一边存放kv值,另一边存放相应的索引。当内存占用80%的时候:(溢写过程,spill)将kv值分区有序写入磁盘;在空的内存中,一边存放kv值,另一边存放索引。
8. 在溢写过程中,要进行分区、排序(快排)(二次排序,先按照partition进行排序,然后在parttion内按照key进行排序)(分区:按照条件输出到不同文件中)(一个切片中的数据,有可能包含若干个分区的数据)
9. 【该过程前可以运行Combiner(本质时一个Reducer),如<b,1><b,1>就会合并成<b,2>】溢写过程生成的文件为spill文件(分区且区内有序)(spill文件保存在{mapred.local.dir}指定的目录中,Map任务结束后就会被删除)(缓存每满足80%,要进行一次溢写,于是生成了多个溢写文件(spill文件))
10. 【该过程前可以运行Combiner】将多个溢写文件通过归并排序合并成一个文件(分区且有序)(5~10步完成,MapTask便生成了最终文件)
11. Combiner合并 
12. 所有MapTask完成后,启动相应的ReduceTask,并告知ReduceTask处理范围(数据分区)
13. ReduceTask从所有MapTask生成的文件中,下载对应分区的文件到本地磁盘
14. 合并文件(归并排序)
15. Reducer一次读取一组(分组规则可以自定义,GroupingCompatator<k, knext>) 
16. 使用OutputFormat(默认TextOutputFormat)调用RecordWriter输出

参考:

[尚硅谷](http://www.atguigu/com)

[MapReduce shuffle过程详解](https://blog.csdn.net/u014374284/article/details/49205885)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值