MapReduce框架原理

Posted 江韵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MapReduce框架原理相关的知识,希望对你有一定的参考价值。

MapReduce框架原理之 InputFormat 数据输入(控制)

文章目录


  mapreduce执行流程图,以下内容讨论的是MapTask阶段的一些问题。

1 切片与MapTask 并行度决定机制

  MapTask 的并行度决定Map 阶段的任务处理并发度,进而影响到整个Job 的处理速度。
  思考:1G 的数据,启动8 个MapTask,可以提高集群的并发处理能力。那么1K 的数据,也启动8 个MapTask,会提高集群性能吗?MapTask 并行任务是否越多越好呢?哪些因素影响了MapTask 并行度?

1.1 MapTask 并行度决定机制

  • 数据块:Block 是HDFS 物理上把数据分成一块一块。数据块是HDFS 存储数据单位
  • 数据切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。数据切片是MapReduce 程序计算输入数据的单位,一个切片会对应启动一个MapTask。

1、一个Job的Map阶段并行度由客户端在提交Job时的切片数决定
2、每一个Split切片分配一个MapTask并行实例处理
3、默认数据切片大小和数据块大小保持一致,避免跨服务器的数据读取操作拖慢运行速度
4、切片时不考虑数据集整体,而是逐个针对每一个文件单独切片

如上图:
  假设切片大小为100M,每个节点的块大小为128M,那么DataNode1节点还剩28M需要跨服务器让DataNode2节点去处理,同理DataNode也需要去处理DataNode2节点剩余的56M和自己本身的44M。频繁的跨服务器数据传输会严重影响任务的执行效率
  而当切片大小设置成块大小时,虽然可能会“浪费掉一部分空间”,但是保证了本节点的数据在本节点处理,不会降低处理效率。

2 Job 提交和切片流程源码详解

2.1 Job提交流程

详细步骤可以自行在程序中debug,总体步骤如下:

waitForCompletion() 
submit(); 
// 1 建立连接 
 connect(); 
 // 1)创建提交Job 的代理 
 new Cluster(getConfiguration()); 
 // (1)判断是本地运行环境还是yarn 集群运行环境 
 initialize(jobTrackAddr, conf); 
 
// 2 提交job 
submitter.submitJobInternal(Job.this, cluster) 
 // 1)创建给集群提交数据的Stag 路径 
 Path jobStagingArea = JobSubmissionFiles.getStagingDir(cluster, conf); 
 // 2)获取jobid ,并创建Job 路径 
 JobID jobId = submitClient.getNewJobID(); 
 // 3)拷贝jar 包到集群 
copyAndConfigureFiles(job, submitJobDir); 
 rUploader.uploadFiles(job, jobSubmitDir); 
 // 4)计算切片,生成切片规划文件 
writeSplits(job, submitJobDir); 
 maps = writeNewSplits(job, jobSubmitDir); 
 input.getSplits(job); 
 // 5)向Stag 路径写XML 配置文件 
writeConf(conf, submitJobFile); 
 conf.writeXml(out); 
 // 6)提交Job,返回提交状态 
status = submitClient.submitJob(jobId, submitJobDir.toString(), 
job.getCredentials());

2.2 提交流程图解

2.3 切片规则

可自行debug你自己的mapreduce程序体会job提交的过程。

3 FileInputFormat 切片机制

3.1 切片机制

 1、简单地按照文件的内容长度进行切片
 2、切片大小,默认等于Block大小
 3、切片时不考虑数据集整体,而是逐个针对每一个文件单独切片

3.2 案例分析

 1、输入数据有两个文件:
   file1.txt 320M
   file2.txt 10M
 2、经过FileInputFormat的切片机制(假设Block大小为128M)运算后,形成的切片信息如下:
  file1.txt.split1-- 0~128
  file1.txt.split2-- 128~256
  file1.txt.split3-- 256~320
  file2.txt.split1-- 0~10M

3.3 FileInputFormat切片大小的参数配置

源码中计算切片大小的公式

Math.max(minSize, Math.min(maxSize, blockSize));
mapreduce.input.fileinputformat.split.minsize=1 默认值为1
mapreduce.input.fileinputformat.split.maxsize= Long.MAXValue 默认值Long.MAXValue
因此,默认情况下,切片大小=blocksize。

切片大小设置

maxsize(切片最大值):参数如果调得比blockSize小,则会让切片变小,而且最终切片大小就等于配置的这个参数的值。
minsize(切片最小值):参数调的比blockSize大,则可以让切片变得比blockSize还大。此时切片大小就超过了块大小。

获取切片信息API

// 获取切片的文件名称
String name = inputSplit.getPath().getName();
// 根据文件类型获取切片信息
FileSplit inputSplit = (FileSplit) context.getInputSplit();

4 TextInputFormat

  FileInputFormat 常见的接口实现类包括:TextInputFormatKeyValueTextInputFormatNLineInputFormatCombineTextInputFormat自定义InputFormat等。
  TextInputFormat 是默认的FileInputFormat 实现类。按行读取每条记录。是存储该行在整个文件中的起始字节偏移量,类型为LongWritable 类型。是这行的内容,不包括任何行终止符(换行符和回车符),类型为Text 类型。

5 CombineTextInputFormat 切片机制

  mapreducer框架默认的TextInputFormat 切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个 MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下
  CombineTextInputFormat 用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask 处理。

5.1 虚拟存储切片最大值设置

CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m

注意:虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值。

5.2 切片机制

  生成切片过程包括:虚拟存储过程和切片过程两部分。

  • 虚拟存储过程
      将输入目录下所有文件大小,依次和设置的setMaxInputSplitSize 值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值2 倍,此时
    将文件均分成2 个虚拟存储块(防止出现太小切片)

      例如setMaxInputSplitSize 值为4M,输入文件大小为8.02M,则先逻辑上分出一个4M。剩余的大小为4.02M,如果按照4M 逻辑划分,就会出现0.02M 的小的虚拟存储文件,所以将剩余的4.02M 文件切分成(2.01M 和2.01M)两个文件

  • 切片过程
      (a)判断虚拟存储的文件大小是否大于setMaxInputSplitSize 值,大于等于则单独形成一个切片。
      (b)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。
      测试举例:若setMaxInputSplitSize=4M,有4个小文件大小分别为1.7M、5.1M、3.4M 以及6.8M 这四个小文件,则虚拟存储之后形成6 个文件块,大小分别为:
    1.7M,(2.55M、2.55M),3.4M 以及(3.4M、3.4M)
    最终会形成3 个切片,大小分别为:
    (1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M

6 CombineTextInputFormat 实例

输入数据
准备4 个小文件
a.txt b.txt c.txt d.txt
期望输出
将输入的小文件合并成一个切片统一处理,即期望一个切片处理4 个文件。

实现:
  根据之前的wordcount进行更改实现。wordcount程序可以参考我之前写的这篇文章
  我们在wordcount的文件输入路径下创建以上四个小文件。先不对Driver类做其他修,运行结果如下:
  由于mapreduce默认使用的是TextInputFormat这种分片机制,也就是说明该机制会为每个小文件都创建一个MapTask。
  接下来在WordcountDriver 中增加如下代码

// 如果不设置InputFormat,它默认用的是TextInputFormat.class 
job.setInputFormatClass(CombineTextInputFormat.class); 
//虚拟存储切片最大值设置4m 
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304); 

  运行程序,并观察运行的切片个数为1,执行了一个MapTask任务。因为我的输入路径下的四个小文件总大小还不够4M,所以就把这四个小文件的四个MapTask任务合并成了一个。

以上是关于MapReduce框架原理的主要内容,如果未能解决你的问题,请参考以下文章

MapReduce 框架原理MapReduce 工作流程 & Shuffle 机制

MapReduce 框架原理

大数据之Hadoop(MapReduce): MapReduce框架原理

打怪升级之小白的大数据之旅(五十)<MapReduce框架原理二:shuffle>

MapReduce 框架原理OutputFormat 数据输出

MapReduce 框架原理InputFormat 数据输入