作业从JobClient端的submitJobInternal()方法提交作业的同时,调用InputFormat接口的getSplits()方法来创建split。默认是使用InputFormat的子类FileInputFormat来计算分片,而split的默认实现为FileSplit(其父接口为InputSplit)。这里要注意,split只是逻辑上的概念,并不对文件做实际的切分。一个split记录了一个Map Task要处理的文件区间,所以分片要记录其对应的文件偏移量以及长度等。每个split由一个Map Task来处理,所以有多少split,就有多少Map Task。下面着重分析这个方法:

 public List<InputSplit> getSplits(JobContext job
) throws IOException {
//getFormatMinSplitSize():始终返回1
//getMinSplitSize(job):获取” mapred.min.split.size”的值,默认为1
long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job)); //getMaxSplitSize(job):获取"mapred.max.split.size"的值,
//默认配置文件中并没有这一项,所以其默认值为” Long.MAX_VALUE”,即2^63 – 1
long maxSize = getMaxSplitSize(job); // generate splits
List<InputSplit> splits = new ArrayList<InputSplit>();
List<FileStatus>files = listStatus(job);
for (FileStatus file: files) {
Path path = file.getPath();
FileSystem fs = path.getFileSystem(job.getConfiguration());
long length = file.getLen();
BlockLocation[] blkLocations = fs.getFileBlockLocations(file, 0, length);
if ((length != 0) && isSplitable(job, path)) {
long blockSize = file.getBlockSize();
//计算split大小
long splitSize = computeSplitSize(blockSize, minSize, maxSize); //计算split个数
long bytesRemaining = length; //bytesRemaining表示剩余字节数
while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) { //SPLIT_SLOP=1.1
int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
splits.add(new FileSplit(path, length-bytesRemaining, splitSize,
blkLocations[blkIndex].getHosts()));
bytesRemaining -= splitSize;
} if (bytesRemaining != 0) {
splits.add(new FileSplit(path, length-bytesRemaining, bytesRemaining,
blkLocations[blkLocations.length-1].getHosts()));
}
} else if (length != 0) {
splits.add(new FileSplit(path, 0, length, blkLocations[0].getHosts()));
} else {
//Create empty hosts array for zero length files
splits.add(new FileSplit(path, 0, length, new String[0]));
}
} // Save the number of input files in the job-conf
job.getConfiguration().setLong(NUM_INPUT_FILES, files.size()); LOG.debug("Total # of splits: " + splits.size());
return splits;
}

  首先计算分片的下限和上限:minSize和maxSize,具体的过程在注释中已经说清楚了。接下来用这两个值再加上blockSize来计算实际的split大小,过程也很简单,具体代码如下:

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

  接下来就是计算实际的分片个数了。针对每个输入文件,计算input split的个数。while循环的含义如下:

  a)  文件剩余字节数/splitSize>1.1,创建一个split,这个split的字节数=splitSize,文件剩余字节数=文件大小 - splitSize

  b)  文件剩余字节数/splitSize<1.1,剩余的部分全都作为一个split(这主要是考虑到,不用为剩余的很少的字节数一些启动一个Map Task)

  

  我们发现,在默认配置下,split大小和block大小是相同的。这是不是为了防止这种情况:

一个split如果对应的多个block,若这些block大多不在本地,则会降低Map Task的本地性,降低效率。

  到这里split的划分就介绍完了,但是有两个问题需要考虑:

1、如果一个record跨越了两个block该怎么办?

  这个可以看到,在Map Task读取block的时候,每次是读取一行的,如果发现块的开头不是上一个文件的结束,那么抛弃第一条record,因为这个record会被上一个block对应的Map Task来处理。那么,第二个问题来了:

2、上一个block对应的Map Task并没有最后一条完整的record,它又该怎么办?

  一般来说,Map Task在读block的时候都会多读后续的几个block,以处理上面的这种情况。不过这部分的代码我还没有看到,等看到了再补充吧。

  本文基于hadoop1.2.1

  如有错误,还请指正

  参考文章:《Hadoop技术内幕 深入理解MapReduce架构设计与实现原理》 董西成

  转载请注明出处:http://www.cnblogs.com/gwgyk/p/4113929.html

hadoop输入分片计算(Map Task个数的确定)的更多相关文章

  1. hadoop 分片与分块,map task和reduce task的理解

    分块:Block HDFS存储系统中,引入了文件系统的分块概念(block),块是存储的最小单位,HDFS定义其大小为64MB.与单磁盘文件系统相似,存储在 HDFS上的文件均存储为多个块,不同的是, ...

  2. 如何在hadoop中控制map的个数

    hadooop提供了一个设置map个数的参数mapred.map.tasks,我们可以通过这个参数来控制map的个数.但是通过这种方式设置map的个数,并不是每次都有效的.原因是mapred.map. ...

  3. 如何在hadoop中控制map的个数 分类: A1_HADOOP 2015-03-13 20:53 86人阅读 评论(0) 收藏

    hadooop提供了一个设置map个数的参数mapred.map.tasks,我们可以通过这个参数来控制map的个数.但是通过这种方式设置map的个数,并不是每次都有效的.原因是mapred.map. ...

  4. (转) 通过input分片的大小来设置map的个数

    摘要 通过input分片的大小来设置map的个数 map inputsplit hadoop 前言:在具体执行Hadoop程序的时候,我们要根据不同的情况来设置Map的个数.除了设置固定的每个节点上可 ...

  5. 字符拆分存入Map计算单词的个数

    ///计算从命令行输入单词的种类与个数//Map<key,Value>Key-->单词:Value-->数量

  6. mapreduce map 的个数

    在map阶段读取数据前,FileInputFormat会将输入文件分割成split.split的个数决定了map的个数.影响map个数(split个数)的主要因素有: 1) 文件的大小.当块(dfs. ...

  7. MapReduce深入理解输入和输出格式(1)-输入分片与记录

    一个输入分片( in put split)就是能够被单个map 操作 处理的输入块. 每一个map 操作只处理一个输入分片,并且一个一个地处理每条记录,也就是一个键/值对.输入分片和记录都是逻辑上的, ...

  8. ${mapred.local.dir}选择策略--Map Task存放中间结果

    上篇说了block在DataNode配置有多个${dfs.data.dir}时的存储策略,本文主要介绍TaskTracker在配置有多个${mapred.local.dir}时的选择策略. mapre ...

  9. hadoop输入格式(InputFormat)

    InputFormat接口(package org.apache.hadoop.mapreduce包中)里包括两个方法:getSplits()和createRecordReader(),这两个方法分别 ...

随机推荐

  1. Ubuntu学习小结(一)

    这段时间,抽空研究了一下Ubuntu,虽然也有过到目前为止使用计算机最作死的经历,但目前已经学会了一些最基本的操作.在这里简单的记录一下,算是吸取的教训,供其他人借鉴. 1.装Ubuntu系统.装Ub ...

  2. mysql 5.7.16安装与给远程连接权限

    ZIP Archive版是免安装的.只要解压就行了.不需要安装.我的放在d盘啦. 1.配置: 也就是my.ini文件的由来. 把my-default.ini(此文件是解压之后,自带的)这个文件复制一下 ...

  3. UVALive 3635 分派

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  4. 微信小程序-上传下载

    wx.uploadFile(OBJECT) 上传 将本地资源上传到开发者服务器.如页面通过 wx.chooseImage(图片)/wx.chooseVideo(视频) 等接口获取到一个本地资源的临时文 ...

  5. sql语句错误

    此错误一般有以下情况造成: 1.配置文件中SQL语句写的有问题 2.传参过程中没有找到sql对应的参数 解决方法: 1.检查sql语句 2.debug启动,查找与sql语句相对应的参数是否存在. 3. ...

  6. left和offsetLeft

    left: 1.当该对象的定位position为absolute时left是相对于拥有定位属性(position的值为默认值"static"时除外)的父级对象的左边距. 例1:当父 ...

  7. angularJS获取json数据(实战)

    学习了这么多天的AngularJS,今天想从实战的角度和大家分享一个简单的Demo--用户查询系统,以巩固之前所学知识.功能需求需要满足两点 1.查询所有用户信息,并在前端展示 2.根据id查询用户信 ...

  8. VS学习

    7.9 今天打开老师给的俄罗斯方块的程序,硬是跑不出来.已经遇到了这几个问题 [1]在项目属性里面C++目录中修改头文件和库函数的绝对路径(基础知识刚学会) [2]errorC1083 SDKDDKe ...

  9. css3 transition动画

    CSS3: 一.transition: <property> <duration> <animation type> <delay> eg: .div{ ...

  10. PHP简单文件上传

    一个简单的PHP上传文件的例子: upload.html <html> <body> <form action="upload.php" method ...