Hadoop(十二)——hadoop之MapReduce理论篇(三)—— FileInputFormat源码解析及切片规则详解...

一、源码

 public List<InputSplit> getSplits(JobContext job) throws IOException {
        long minSize = Math.max(this.getFormatMinSplitSize(), getMinSplitSize(job));
        long maxSize = getMaxSplitSize(job);
        List<InputSplit> splits = new ArrayList();
        List<FileStatus> files = this.listStatus(job); // 1. 获取input目录下的所有文件
        Iterator i$ = files.iterator();
        // 2. 遍历目录下的所有文件
        while(true) {
            while(i$.hasNext()) {
                FileStatus file = (FileStatus)i$.next();
                Path path = file.getPath();
                FileSystem fs = path.getFileSystem(job.getConfiguration());
                long length = file.getLen(); // 获取文件大小
                BlockLocation[] blkLocations = fs.getFileBlockLocations(file, 0L, length);
                if(length != 0L && this.isSplitable(job, path)) {
                    long blockSize = file.getBlockSize();
                    //计算切片大小 默认情况下splitSize=blockSize=128M
                    long splitSize = this.computeSplitSize(blockSize, minSize, maxSize);
                    long bytesRemaining;
                    //假设这个文件大小是300M:aa.txt
                    //开始切片,形成第1个切片:aa.txt—0:128M 
                    //第2个切片aa.txt—128:256M
                    //第3个切片aa.txt—256M:300M(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片)
                    for(bytesRemaining = length; (double)bytesRemaining / (double)splitSize > 1.1D; bytesRemaining -= splitSize) {
                        int blkIndex = this.getBlockIndex(blkLocations, length - bytesRemaining);
                       //将切片信息写到一个切片规划文件中
                        splits.add(new FileSplit(path, length - bytesRemaining, splitSize, blkLocations[blkIndex].getHosts()));
                    }

                    if(bytesRemaining != 0L) {
                        splits.add(new FileSplit(path, length - bytesRemaining, bytesRemaining, blkLocations[blkLocations.length - 1].getHosts()));
                    }
                } else if(length != 0L) {
                    //将切片信息写到一个切片规划文件中
                    splits.add(new FileSplit(path, 0L, length, blkLocations[0].getHosts()));
                } else {
                    //将切片信息写到一个切片规划文件中
                    splits.add(new FileSplit(path, 0L, length, new String[0]));
                }
            }

            job.getConfiguration().setLong("mapreduce.input.num.files", (long)files.size());
            LOG.debug("Total # of splits: " + splits.size());
            return splits;//3. 整个切片的核心过程在getSplit()方法中完成
        }
        //4. 数据切片只是在逻辑上对输入数据进行分片,并不会再磁盘上将其切分成分片进行存储。
        	//InputSplit只记录了分片的元数据信息,比如起始位置、长度以及所在的节点列表等。
        //5. 注意:block是HDFS上物理上存储的存储的数据,切片是对数据逻辑上的划分。
    }
	//提交切片规划文件到yarn上,yarn上的MrAppMaster就可以根据切片规划文件计算开启maptask个数。

二、FileInputFormat切片规则描述

  1. 默认的切片机制:
  • (1)简单地按照文件的内容长度进行切片
  • (2)切片大小,默认等于block大小
  • (3)切片时不考虑数据集整体,而是逐个针对每一个文件单独切片
	比如待处理数据有两个文件:
	file1.txt    320M
	file2.txt    10M
	经过FileInputFormat的切片机制运算后,形成的切片信息如下:  
	file1.txt.split1--  0~128
	file1.txt.split2--  128~256
	file1.txt.split3--  256~320
	file2.txt.split1--  0~10M
  1. FileInputFormat切片大小的参数配置
  • 通过分析源码,在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还大。
  1. 获取切片信息API
// 根据文件类型获取切片信息
FileSplit inputSplit = (FileSplit) context.getInputSplit();
// 获取切片的文件名称
String name = inputSplit.getPath().getName();

三、FileInputFormat源码图片流程描述

四、CombineTextInputFormat切片机制

  1. 关于大量小文件的优化策略
  • 1)默认情况下TextInputformat对任务的切片机制是按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个maptask,这样如果有大量小文件,就会产生大量的maptask,处理效率极其低下。
  • 2)优化策略
    • (1)最好的办法,在数据处理系统的最前端(预处理/采集),将小文件先合并成大文件,再上传到HDFS做后续分析。
    • (2)补救措施:如果已经是大量小文件在HDFS中了,可以使用另一种InputFormat来做切片(CombineTextInputFormat),它的切片逻辑跟TextFileInputFormat不同:它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个maptask。
    • (3)优先满足最小切片大小,不超过最大切片大小
      • CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
      • CombineTextInputFormat.setMinInputSplitSize(job, 2097152);// 2m
    • 举例:0.5m+1m+0.3m+5m=2m + 4.8m=2m + 4m + 0.8m
  • 3)具体实现步骤
	// 如果不设置InputFormat,它默认用的是TextInputFormat.class
	job.setInputFormatClass(CombineTextInputFormat.class)
	CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
	CombineTextInputFormat.setMinInputSplitSize(job, 2097152);// 2m

转载于:https://my.oschina.net/ittzg/blog/3068797

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实 验 报 告 (2014 / 2015 学年 第 二 学期) "课程名称 "云计算 " "实验名称 "基于Hadoop的数据分析 " "实验时间 "2015 "年 "5 "月 "20 "日 " "指导单位 " " "指导教师 " " "学生姓名 " "班级学号 " " "学院(系) " "专 业 " " 实 验 报 告 "实验名称 " "指导教师 " " "实验类型 "上机 "实验学时 "2 "实验时间 "2015.5.20 " "实验目的和要求 " "【实验要求】 " "掌握基于Hadoop单机版的数据分析 " "【实验目的】 " "学会利用Hadoop对不同数据集的分析与挖掘; " "二、实验环境 " "虚拟机Ubuntu14.04,hadoop-1.2.1,eclipse-SDK-4.3.1 " "、实验原理及内容 " "(1)在第一次实验的基础上安装eclipse " "1.将eclipse解压到usr/local目录下: " "sudo tar xzvf eclipse-SDK-4.3.1-linux-gtk-x86_64.tar.gz " "-C/usr/local " "2.授权:sudo chmod -R 777 /usr/local/eclipse " " " "将hadoop插件拷贝到/usr/local/eclipse/plugins下 " " " " " " " " " " " "4.设置eclipse的Java环境:在eclipse下创建一个jre文件夹sudo mkdir jre,进 " "入该文件夹:cd jre, " "加入一条连接指令ln -s /usr/lib/jvm/java-7-sun/bin bin " "(2)在eclipse中添加Map/Reduce:点击上方window选项,依次选择open " "perspective,other,Map、Reduce,如下图所示: " " " "(3)设置Map/Reduce location,选择Map/Reduce locations,new hadoop " "location,将其中的内容设置成下图所示的内容: " " " "设置Advanced parameters中的tmp文件夹位置为/usr/local/hadoop/tmp,如下图 " "所示: " " " "(4)设置hadoop的安装路径:依次点击window,preferences,Hadoop Map/Reduce " ",设置hadoop安装路径为/usr/local/hadoop " " " "(5)在桌面新建个文件,如图所示: " " " " " " " "新建一个Map/Reduce " "Project:右击左侧空白处,选择新建一个如下图所示的Map/Reduce Project: " " " "点击Next,输入工程名为average,再点击finish。 " "新建一个Java class:右击左侧的average,依次选择New,class,设置内容如下 " "图所示: " " " " " " " " " "点击finish完成。 " "(8)加入Java代码: " "package com.hebut.mr; " "import java.io.IOException; " "import java.util.Iterator; " "import java.util.StringTokenizer; " "import org.apache.hadoop.conf.Configuration; " "import org.apache.hadoop.fs.Path; " "import org.apache.hadoop.io.IntWritable; " "import org.apache.hadoop.io.LongWritable; " "import org.apache.hadoop.io.Text; " "import org.apache.hadoop.mapreduce.Job; " "import org.apache.hadoop.mapreduce.Mapper; " "import org.apache.hadoop.mapreduce.Reducer; " "import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; " "import org.apache.hadoop.mapreduce.lib.input.TextInputFormat; " "import org.apache.hadoop.mapreduce.lib.output.FileO

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值