Hadoop中block块大小和split切片大小会影响到MapReduce程序在运行过程中的效率、map的个数。在本文中,以经典入门案例WordCount为例,通过debug的方式跟踪源代码,来分析hadoop中split的计算方法。

前期准备

wc.txt的准备 
单词统计,以空格为分割符对单词进行切割。因此wc.txt中的单词都以空格进行分割 
mr核心部分介绍 
map 
提取每一行,String[] arr = line.split(” “);

for(String word : arr){context.write(new Text(word),new IntWritable(1));
}

reduce 
对每一个key的个数进行迭代,计算总数。

修改HDFS的文件块大小

hdfs-default.xml 
首先查看默认的配置信息 
文件块的大小

<property><name>dfs.blocksize</name><value>134217728</value><description>The default block size for new files, in bytes.You can use the following suffix (case insensitive):k(kilo), m(mega), g(giga), t(tera), p(peta), e(exa) to specify the size (such as 128k, 512m, 1g, etc.),Or provide complete size in bytes (such as 134217728 for 128 MB).</description>
</property>

最小文件块的大小

<property><name>dfs.namenode.fs-limits.min-block-size</name><value>1048576</value><description>Minimum block size in bytes, enforced by the Namenode at createtime. This prevents the accidental creation of files with tiny blocksizes (and thus many blocks), which can degradeperformance.</description>
</property>

hdfs-site.xml 
了解默认的配置信息之后,对其进行修改

<property><name>dfs.blocksize</name><value>512</value>   //块大小需要能够整除校验和   需要符合校验和的倍数要求(切记!!必须为512的倍数)
</property>
<property><name>dfs.namenode.fs-limits.min-block-size</name><value>10</value>
</property>

通过命令行查看属性是否修改成功

$>hdfs getconf -confKey dfs.blocksize
$>hdfs getconf -confKey dfs.namenode.fs-limits.min-block-size

关键部分源码解析

对所涉及到的关键部分,进行解析 
org.apache.hadoop.mapreduce.JobSubmitter类

  private int writeSplits(org.apache.hadoop.mapreduce.JobContext job,Path jobSubmitDir) throws IOException,InterruptedException, ClassNotFoundException {// 得到配置信息JobConf jConf = (JobConf)job.getConfiguration();int maps;// 判断是否是新的Mapperif (jConf.getUseNewMapper()) {// 计算新的切片信息// 作业       job:              com.sun.jdi.InvocationException occurred invoking method.// 作业提交目录 jobSubmitDir:       /tmp/hadoop-yarn/staging/zhaotao/.staging/job_1496761683234_0001maps = writeNewSplits(job, jobSubmitDir);} else {maps = writeOldSplits(jConf, jobSubmitDir);}return maps;}...private <T extends InputSplit>int writeNewSplits(JobContext job, Path jobSubmitDir) throws IOException,InterruptedException, ClassNotFoundException {// 得到配置信息Configuration conf = job.getConfiguration();// 得到输入格式InputFormat<?, ?> input =ReflectionUtils.newInstance(job.getInputFormatClass(), conf);// 得到splits切片的集合,具体的值为://  [hdfs://s100/data/wc.txt:0+150, hdfs://s100/data/wc.txt:150+150, hdfs://s100/data/wc.txt:300+150, hdfs://s100/data/wc.txt:450+150, hdfs://s100/data/wc.txt:600+158]总共切了5个List<InputSplit> splits = input.getSplits(job);T[] array = (T[]) splits.toArray(new InputSplit[splits.size()]);// sort the splits into order based on size, so that the biggest// go firstArrays.sort(array, new SplitComparator());JobSplitWriter.createSplitFiles(jobSubmitDir, conf, jobSubmitDir.getFileSystem(conf), array);return array.length;}

org.apache.hadoop.mapreduce.lib.input.FileInputFormat类

  public List<InputSplit> getSplits(JobContext job) throws IOException {StopWatch sw = new StopWatch().start();// 通过getFormatMinSplitSize()方法  取得最小切片的大小为一个固定值(可通过配置文件配置得到)为0// 通过getMinSplitSize()方法 得到最小切片值为1// minSize的值为1long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));// maxSize的值为:9223372036854775807long maxSize = getMaxSplitSize(job);// generate splits// 创建一个集合List<InputSplit> splits = new ArrayList<InputSplit>();//  得到hdfs的文件夹列表List<FileStatus> files = listStatus(job);// 得到每个文件的状态,进行for循环for (FileStatus file: files) {// 取到文件的路径Path path = file.getPath();// 取到文件的长度long length = file.getLen();if (length != 0) {// 文件块位置的数组BlockLocation[] blkLocations;if (file instanceof LocatedFileStatus) {// 通过getBlockLocations()方法得到文件块的位置// blkLocations的值:[0,512,s103,s101,s104, 512,246,s103,s104,s102]  为两块文件块blkLocations = ((LocatedFileStatus) file).getBlockLocations();} else {FileSystem fs = path.getFileSystem(job.getConfiguration());blkLocations = fs.getFileBlockLocations(file, 0, length);}// 判断文本文件是否可切割if (isSplitable(job, path)) {// 得到块大小// blockSize的值为512// 切片大小与块大小、最小切片值、最大切片值有关long blockSize = file.getBlockSize();// 计算切片大小// blockSize=512;minSize=1;maxSize=9223372036854775807// splitSize的值为512long splitSize = computeSplitSize(blockSize, minSize, maxSize);...// 最终返回的值为一个切片集合// 具体的值为:[hdfs://s100/data/wc.txt:0+150, hdfs://s100/data/wc.txt:150+150, hdfs://s100/data/wc.txt:300+150, hdfs://s100/data/wc.txt:450+150, hdfs://s100/data/wc.txt:600+158]总共切了5个return splits;...// 得到切片大小的一个下限值,返回的是一个最小切片的字节数protected long getFormatMinSplitSize() {return 1;}...public static long getMinSplitSize(JobContext job) {// SPLIT_MINSIZE = mapreduce.input.fileinputformat.split.minsize(该配置项的默认值为0)// job.getConfiguration().getLong(SPLIT_MINSIZE, 1L) = 0return job.getConfiguration().getLong(SPLIT_MINSIZE, 1L);}...public static long getMaxSplitSize(JobContext context) {// SPLIT_MAXSIZE = mapreduce.input.fileinputformat.split.maxsize// Long.MAX_VALUE的意思为取长整型的最大值9223372036854775807// context.getConfiguration().getLong(SPLIT_MAXSIZE,Long.MAX_VALUE)的值为9223372036854775807return context.getConfiguration().getLong(SPLIT_MAXSIZE, Long.MAX_VALUE);}...protected long computeSplitSize(long blockSize, long minSize,long maxSize) {// 先在maxSize与blockSize之间选择小的,再使用该值与minSize之间取得大的值// 就是取了三个值之间的中间值return Math.max(minSize, Math.min(maxSize, blockSize));}

split计算方法

通过对源代码的跟踪,将split的计算方法总结如下: 
minSize = 1(默认) (属性名字:mapreduce.input.fileinputformat.split.minsize) 
maxSize = Long.MAX_VALUE(默认) (属性名字:mapreduce.input.fileinputformat.split.maxsize) 
blockSize = 512 (属性名字:dfs.blocksize=128mb默认值) 
计算方法:max(minSize,min(blockSize,maxSize)) 
根据上述数据,所以该过程中的切片大小为512

考究Hadoop中split的计算方法相关推荐

  1. Hadoop中Block和Split区别

    两者是从不同的角度来定义的: HDFS以固定大小的block为基本单位存储数据(分布式文件系统,实际存储角度,物理存储单位): MapReduce以split作为处理单位(编程模型角度,逻辑单位): ...

  2. hadoop中MapReduce中压缩的使用及4种压缩格式的特征的比较

    在比较四中压缩方法之前,先来点干的,说一下在MapReduce的job中怎么使用压缩. MapReduce的压缩分为map端输出内容的压缩和reduce端输出的压缩,配置很简单,只要在作业的conf中 ...

  3. Hadoop中任务提交运行流程

    在Hadoop中提交一个任务大致分为6个步骤,分别为: 作业提交 -> 作业初始化 –> 任务分配 –> 任务执行 –> 更新任务执行进度和状态 -> 作业完成 目录 作 ...

  4. WordCount作业提交到FileInputFormat类中split切分算法和host选择算法过程源码分析

    参考 FileInputFormat类中split切分算法和host选择算法介绍  以及 Hadoop2.6.0的FileInputFormat的任务切分原理分析(即如何控制FileInputForm ...

  5. hadoop中如何控制map的数量

    hadoop中如何控制map的数量 @(HADOOP)[hadoop] hadooop提供了一个设置map个数的参数mapred.map.tasks,我们可以通过这个参数来控制map的个数.但是通过这 ...

  6. 4种常用压缩格式在hadoop中的应用

    目前在hadoop中用得比较多的有lzo,gzip,snappy,bzip2这4种压缩格式,笔者根据实践经验介绍一下这4种压缩格式的优缺点和应用场景,以便大家在实践中根据实际情况选择不同的压缩格式. ...

  7. 《小白兔到大黑牛》第十四篇Hadoop中五个进程作用

    问题导读: 1.job的本质是什么? 2.任务的本质是什么? 3.文件系统的Namespace由谁来管理,Namespace的作用是什么? 4.Namespace 镜像文件(Namespace ima ...

  8. 深度分析如何在Hadoop中控制Map的数量

    深度分析如何在Hadoop中控制Map的数量 guibin.beijing@gmail.com 很多文档中描述,Mapper的数量在默认情况下不可直接控制干预,因为Mapper的数量由输入的大小和个数 ...

  9. hadoop block split 区别

    Hadoop权威指南(第三版)P31 Hadoop divides the input to a MapReduce job into fixed-size pieces called input s ...

最新文章

  1. mysql查询唯一单词_MySql从表中获取唯一单词列表,其中字段中的值用逗号分隔
  2. java内部错误2755_内部错误2755.(安装软件出问题啦)
  3. Android studio .9图片造成的错误总结
  4. Android系统源代码下载
  5. MCSDK HUA Demonstration Guide
  6. 打趴系统的不一定是技术
  7. JMX和Spring –第2部分
  8. 深入理解Plasma(一)Plasma 框架
  9. RainMeter学习1
  10. asp与ACCESS数据库的连接及基本操作
  11. 香港流行乐坛三十年(很好的回忆)
  12. 核密度估计_拔剑-浆糊的传说_新浪博客
  13. Gitlab 登录报422错误,账号密码是对的?
  14. 谷歌浏览器87版本 iframe_谷歌Chrome的“混合内容”更新将会影响电商网站,自建站卖家如何应对?...
  15. pythontkinter键盘_Python笔记之Tkinter(Key键盘事件)
  16. NOI 1789:算24
  17. 查询mysql 的内存使用_mysql查看内存使用情况
  18. 微信公众号开发,扫描二维码事件推送丢失参数问题
  19. arcgis 栅格数据 邻域计算_ArcGIS空间分析基本操作
  20. ChatGPT 被大面积封号,到底发生什么了?

热门文章

  1. oracle主从表分离怎么实时更新数据_高可用数据库主从复制延时的解决方案
  2. idea2020shezhi代码检查级别_ICT技术:阿里巴巴代码缺陷检测探索与实践
  3. LVS负载均衡群集(LVS-NAT搭建)
  4. 使用gcc编译c语言程序,用GCC编译C ++程序
  5. python鼠标碰撞_获取鼠标指针测试item之间的碰撞
  6. 背完这442句英语,你的口语绝对不成问题了
  7. iphone文件访问ftp服务器,将文件上传到iPhone上的FTP服务器
  8. python如何卸载模块cmd_使用cmd python模块时,如何使程序正常崩溃?
  9. 三星s窗口共享android,三星s窗口共享(SideSync pc端)
  10. python获取控制台输出_Python | 用Python获取Windows控制台输出