大数据面试题--MapReduce篇

MapReduce任务执行的11个步骤

1.运行job任务
2.获取ApplicationID|JobID
3.Copy Job资源到HDFS-切片信息、配置信息、代码片段
4.提交任务给ResourceManager
5.RM->NM消耗一个Container资源,用于启动MRAppMaster
6.MRAppMaster初始化任务,完成任务调度前的准备工作
7.MRAppMaster查询输入切片信息、配置,进而获取第1、2阶段任务并行度
8.MRAppMaster连接RM获取计算资源
9.MRAppMaster连接NM消耗Container|YarnChild
10.YarnChild获取切片信息和代码片段
11.YarnChild调用MapTask或者ReduceTask

ResourceManager:负责任务资源的统一调度,管理NodeManager资源,启动MRAppMaster
NodeManager:用于管理本机上的计算资源。默认会将本机的计算资源拆分成8个等份,每个等份抽象成Container
MRAppMaster:任何一个执行的任务都会有一个MRAppMaster负责YarnChild任务的执行和监测
YarnChild:是具体执行的MapTask或者是ReduceTask的统称。

如何书写一个Job提交

1.创建Job对象
2.指定输入输出格式类
3.指定输入和写出格式
4.设置Mapper|Reduce逻辑
5.设置Mapper|Reducer输出key-value类型
6.Job提交

注意: 需要设定numReduceTasks数量/设置Mapper端输出压缩/如果任务支持Combiner、必须设置Combiner

MapReduce切片计算方案

SPLIT_SLOP=1.1,即当划分后剩余文件大小除以splitSize大于128的1.1倍时,会继续循环切分,小于1.1倍时退出循环,将剩下的文件大小归到一个切片上去。

while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {
     int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
     splits.add(makeSplit(path, length-bytesRemaining, splitSize,blkLocations[blkIndex].getHosts(),
                  blkLocations[blkIndex].getCachedHosts()));
     bytesRemaining -= splitSize;
}
为什么说MapReduce不擅长处理小文件?

默认情况下,TextInputFormat对任务的切片机制是规则切片,不管文件多小,都会是一个单独的切片,都会交给MapTask,如果有大量的小文件,就会产生大量的MapTask,导致处理效率极其低下

  • 优化方法
    在数据处理之前,先将小文件合并成大文件,再上传到HDFS上做后续分析
CombineTextInputFormat怎么专门处理小文件?

对于HDFS中的大量小文件,可以使用CombineTextInputFormat进行切片,它的切片逻辑与FileTextInputFormat不同,它可以将多个小文件从逻辑上划分到一个切片中,这样多个小文件就可以交给一个MapTask

MapReduce Shuffle

大数据面试题--MapReduce篇_第1张图片
大数据面试题--MapReduce篇_第2张图片

  • 计算切片
    有几个切片就有几个map task
  • 环形缓冲区
    经过map函数的逻辑处理后的数据输出之后,会通过OutPutCollector收集器将数据收集到环形缓冲区保存。环形缓冲区的大小默认为100M,当报存的数据达到80%时,就将缓冲区的数据溢出到磁盘上保存。
  • 溢出
    程序会对溢出的数据进行分区(默认HashPartition)和排序(默认根据key进行快排)
    缓冲区不断溢出的数据形成多个小文件
  • 合并
    溢出的多个小文件各个区合并在一起(0区和0区合并成一个0区),形成大文件。
    通过归并排序保证区内的数据有序。
  • shuffle
    从数据进入环形缓冲区到reducetask之间,即map任务和reduce任务之间的数据流称为shuffle(混洗),而过程5最能体现出混洗这一概念。一般情况下,一个reduce任务的输入数据来自于多个map任务,多个reduce任务的情况下就会出现如图过程5所示的

每个reduce任务从map的输出数据中获取属于自己的那个分区的数据。

  • 合并
    运行reducetask的节点通过过程5,将来自多个map任务的属于自己的分区数据下载到本地磁盘工作目录。这多个分区文件通过归并排序合并成大文件,并根据key值分好组(key值相同的,value值会以迭代器的形式组在一起)。
  • reducetask
  • reducetask从本地工作目录获取已经分好组并且排好序的数据,将数据进行reduce函数中的逻辑处理。
  • 输出
    每个reducetask输出一个结果文件。
什么是MapReduce计算中的数据倾斜?
  • 产生原因
    在MapReduce做计算的时候,由于不合理的key,导致出现数据分布不均匀的现象,称之为数据倾斜。
  • 解决思路
    选择合适的key作为统计依据,使得数据能够在分区中均匀分布,一般要对分析的数据有一定的预判。
  • 方案一
    设置Map和Reduce的任务的数量
  • 方案二
    设置任务运行的并行度
  • 方案三
    增加相应节点虚拟机的内存大小
  • 方案四
    自定义Partition
  • 方案五
    开启map端的压缩
    可以减少reduce shuffle过程中的网络带宽,不足之处在于计算过程中需要消耗额外的CPU进行数据的压缩和解压缩。
    注意: 此方案适合在集群环境下使用,如果是本地测试会报not a gzip file的错误。如果现有100亿条无序的数字需要进行排序,此时在reduce端下载map端的数据就会占用大量的带宽。
  • 方案六
    自定义Combiner
    先对map端的文件排序结果进行合并优化,再执行reduce端的方法进行处理,这样传输的数据量就会有一个质的下降
    注意: 自定义Combiner结果类型必须一致;统计过程必须支持局部计算
MapReduce能否对key做全局排序?

可以。

  • 方案一

MapReduce只能保证一个分区内的数据是key有序的,一个分区对应一个reduce,因此只有一个reduce就保证了数据全局有序

缺点: 不能用到集群的优势。

  • 方案二
    多个reduce情况下,可以按照key进行分区,通过MapReduce的默认分区函数HashPartition将不同范围的key发送到不同的reduce处理。

例如一个文件中有key值从1到10000的数据,我们使用两个分区,将1到5000的key发送到partition1,然后由reduce1处理,5001到10000的key发动到partition2然后由reduce2处理,reduce1中的key是按照1到5000的升序排序,reduce2中的key是按照5001到10000的升序排序,这样就保证了整个MapReduce程序的全局排序。

缺点:
1.当数据量大时会出现OOM(内存溢出)
2.会出现数据倾斜

  • 方案三
    Hadoop提供了TotalOrderPartitionner类用于实现全局排序的功能,并且解决了OOM和数据倾斜的问题。

TotalOrderPartitioner类提供了数据采样器,对key值进行部分采样,然后按照采样结果寻找key值的最佳分割点,将key值均匀的分配到不同的分区中。

TotalOrderPartitioner 类提供了三个采样器,分别是:

SplitSampler 分片采样器:从数据分片中采样数据,该采样器不适合已经排好序的数据
RandomSampler随机采样器:按照设置好的采样率从一个数据集中采样,是一个优秀的通配采样器
IntervalSampler间隔采样机:以固定的间隔从分片中采样数据,对于已经排好序的数据效果非常好

你可能感兴趣的:(大数据面试题,面试题,大数据,mapreduce)