MapReduce Shuffle 原理以及优化

MapReduce Shuffle 原理以及优化

1、MapReduce 编程模型

Hadoop MapReduce 是一个分布式计算框架,用于编写批处理应用程序;
数据以一条记录为单位经过 map 方法映射成KV,相同的key为一组,这一组数据调用一次 reduce方法,在方法内迭代计算着一组数据。

2、MapReduce 的实现原理

Client 提交

客户端在进行submit() 之前,会获取待处理数据的信息,然后做出执行前的规划;很重要,支撑了计算向数据移动和计算的并行度;

源码中

  • 1,Checking the input and output specifications of the job.
  • 2,Computing the InputSplits for the job. // split ->并行度和计算向数据移动就可以实现了
  • 3,Setup the requisite accounting information for the DistributedCache of the job, if necessary.
  • 4,Copying the job’s jar and configuration to the map-reduce system directory on the distributed file-system.
  • 5,Submitting the job to the JobTracker and optionally monitoring it’s status

对于 split 的计算:

minSize = 1
maxSize = Long.Max
blockSize = file
splitSize = Math.max(minSize, Math.min(maxSize, blockSize)); //默认split大小等于block大小
切片split是一个窗口机制:(调大split改小,调小split改大)

切片信息:

split:解耦 存储层和计算层
1,file
2,offset
3,length
4,hosts //支撑的计算向数据移动

MapTask 阶段

input -> map方法 -> output

  1. 格式化记录(TextInputFormat->LineRecordreader),以记录为单位调用 map 方法;
  2. map 输出<K,V > 的记录,通过分区器算出分区 P 形成三元组,序列化成字节数组后写到环形缓冲区
  3. 环形缓冲区两端方 <K,V> 索引;索引是固定长度16B:1) P 2) Key Start 3) Value Start 4)Value Length
  4. 默认达到环形缓冲区的 80 % 溢写磁盘;快速排序80%数据,同时map输出的线程向剩余的空间写;快速排序的过程:是比较key排序,但是移动的是索引
  5. 溢写磁盘的过程发生二次排序,即分区有序,分区内key有序;
  6. 对多次溢写的小文件进行合并,combiner

ReduceTask 阶段

  1. Reduce Task 从 MRAppMaster 得知,对应分区内数据所在的位置,拉取对应分区的数据;
  2. ReduceTask 拉取数据到磁盘,之后合并文件进行归并排序;
  3. 按照一组记录为单位调用 reduce 方法;
  4. 结果写入磁盘;

3、MapReduce 过程优化

小文件优化

1、从存储方面来说:hadoop的存储每个文件都会在NameNode上记录元数据,如果同样大小的文件,文件很小的话,就会产生很多文件,造成NameNode的压力
2、从读取方面来说:同样大小的文件分为很多小文件的话,会增加磁盘寻址次数,降低性能
3、从计算方面来说:我们知道一个map默认处理一个分片或者一个小文件,如果map的启动时间都比数据处理的时间还要长,那么就会造成性能低,而且在map端溢写磁盘的时候每一个map最终会产生reduce数量个数的中间结果,如果map数量特别多,就会造成临时文件很多,而且在reduce拉取数据的时候增加磁盘的IO。

怎么处理

  1. 从源头干掉,也就是在hdfs上我们不存储小文件,也就是数据上传hdfs的时候我们就合并小文件
  2. 在FileInputFormat读取入数据的时候我们使用实现类CombineFileInputFormat读取数据,在读取数据的时候进行合并。
  3. 使用hadoop 自带的 archive

MapReduce 过程优化

提交阶段:

对于小文件:可以使用合适的文件的读取类,进行小文件合并
任务信息:上传的 Jar、分片信息,等资源信息会提交到 hdfs 的临时目录中,默认会有10个副本;可以通过参数 mapreduce.client.submit.file.replication 控制副本的数量(集群规模较大的时候);

MapTask 阶段:

Split 大小:一个 split 会启动一个 MapTask 执行,所以需要合理设置 split 大小;Math.max(minSize, Math.min(maxSize, blockSize))
MapTask 资源:mapreduce.map.memory.mb 默认1G, mapreduce.map.cpu.vcores 默认为 1
Map 任务向磁盘溢写之前会先写入环形缓冲区,可以较少溢写的次数,减少磁盘IO;当达到磁盘文件达到一定量时,会进行小文件的合并,可以增大合并文件的数量;

设置环形缓冲区大小:mapreduce.task.io.sort.mb

设置环形缓冲区溢写阈值:mapreduce.map.sort.spill.percent

设置合并磁盘文件个数:mapreduce.task.io.sort.factor

Map 输出文件的数据压缩可以减少数据量的大小:mapreduce.map.output.compress(default:false)

压缩的方式:mapreduce.map.output.compress.codec

mapreduce.task.io.sort.mb        #排序map输出所需要使用内存缓冲的大小,以兆为单位, 默认为100
mapreduce.map.sort.spill.percent #map输出缓冲和用来磁盘溢写过程的记录边界索引,这两者使用的阈值,默认0.8
mapreduce.task.io.sort.factor    #排序文件时,一次最多合并的文件数,默认10
mapreduce.map.output.compress    #在map溢写磁盘的过程是否使用压缩,默认false
org.apache.hadoop.io.compress.SnappyCodec  #map溢写磁盘的压缩算法,默认org.apache.hadoop.io.compress.DefaultCodec
mapreduce.shuffle.max.threads    #该参数表示每个节点管理器的工作线程,用于map输出到reduce,默认为0,表示可用处理器的两倍

ReduceTask 阶段:

  1. Reduce 个数设置:mapreduce.job.reduces
  2. Reduce 资源设置:mapreduce.reduce.memory.mb , mapreduce.reduce.cpu.vcores
  3. Reduce 进行数据拉取时,可以设置拉取时的并行度 : mapreduce.reduce.shuffle.parallelcopies
  4. Reduce Task 下载任务时,最大的下载时间段可以设置 : mapreduce.reduce.shuffle.read.timeout
  5. Reduce Task 拉取过来的数据会先放入内存缓冲区,当达到一定量之后才溢写到磁盘; 该内存基于 JVM 的堆大小;mapreduce.reduce.s huffle.input.buffer.percent(default 0.7) shuffle 在 reduce 内存中的最大值为: 0.7 × maxHeap of reduce task,内存到磁盘的阈值:mapreduce.reduce.shuffle.merge.percent(default0.66)
  6. 对于拉取的数据,进行归并排序时的合并因子:mapreduce.task.io.sort.factor 对于 map 输出很多,可以选择提高该值;
mapreduce.reduce.shuffle.parallelcopies #把map输出复制到reduce的线程数,默认5
mapreduce.task.io.sort.factor  #排序文件时一次最多合并文件的个数
mapreduce.reduce.shuffle.input.buffer.percent #在shuffle的复制阶段,分配给map输出缓冲区占堆内存的百分比,默认0.7
mapreduce.reduce.shuffle.merge.percent #map输出缓冲区的阈值,用于启动合并输出和磁盘溢写的过程
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值