MapReduce切片

文章详细介绍了HadoopMapReduce中数据切片的概念,每个MapTask处理的数据单元称为切片。切片大小通常与数据块大小一致,以避免数据的分割重组导致的资源消耗。在代码分析部分,展示了获取和配置数据块,以及判断切片合法性的过程,包括对文件类型、文件大小和压缩文件的处理。最后,总结了配置、合法性验证和切片处理的三个主要步骤。
摘要由CSDN通过智能技术生成

1.概念

1.切片是什么?

每个MapTask处理的数据单元,就叫片,也就是说,MapTask与片是一对一的关系。

2.切片大小如何设置?

切片大小默认与块大小一致

3.切片大小定义的理由

反证法:假设,我们不使用块大小来定义, 设当前块大小为128M, 片大小为100M。我们需要计算HDFS中的数据,要从里面取300M的数据。 首先,第一个块取出来,切, 还剩28M,取第二个块,切72M, 然后第二块还剩56M 再取第三块,再取44M。这样的结果,显然就是将数据块的数据分割重组,这样大大增加了资源的消耗。不论是比当前块大,还是比当前块小,都避免不了数据块的分割重组,所以,与块大小一致是目前最优。

2.代码分析

这里分成两步:
一: 获取数据并存储及配置
二: 执行切片 判断合法性等都在第二步中了


 public List<InputSplit> getSplits(JobContext job) throws IOException {
 		// 1.准备工作 获取数据,并配置相关过滤配置
 		
 		// 1.1 计时器开启
        StopWatch sw = (new StopWatch()).start();
        
        // 1.2 配置尺寸
        // 1.2.1 配置最小尺寸   getFormatMinSplitSize是1
        // getMinSplitSize(job) 是从配置文件中读取如果不存在,默认也是1
        // mapreduce.input.fileinputformat.split.minsize可以修改配置文件修改
        long minSize = Math.max(this.getFormatMinSplitSize(), getMinSplitSize(job));
        // 1.2.2 配置最大尺寸
        // mapreduce.input.fileinputformat.split.maxsize Long.MAX_VALUE
        // 可以通过修改配置文件修改 默认是Long最大值
        long maxSize = getMaxSplitSize(job);
        // 1.3 获取元数据文件
        List<InputSplit> splits = new ArrayList();
        List<FileStatus> files = this.listStatus(job);
        // 1.4 文件判断符,是否需要掠过文件夹
        // 参数一:getInputDirRecursive(job):  默认false mapreduce.input.fileinputformat.input.dir.recursive 
        // 参数二:默认false 
        //可以修改mapreduce.input.fileinputformat.input.dir.nonrecursi为true修改
        // 也就是说主要取决于第二个配置
        boolean ignoreDirs = !getInputDirRecursive(job) && job.getConfiguration().getBoolean("mapreduce.input.fileinputformat.input.dir.nonrecursive.ignore.subdirs", false);
        
        // 2. 数据处理阶段(这里将校验和处理放在了一起)
        Iterator var10 = files.iterator();
		
        while(true) {
            while(true) {
                while(true) {
                    FileStatus file;
                    // 2.1 对文件夹的处理 将元数据全部过一遍,怎么空了就出去了
                    do {
                        if (!var10.hasNext()) {
                            job.getConfiguration().setLong("mapreduce.input.fileinputformat.numinputfiles", (long)files.size());
                            sw.stop();
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("Total # of splits generated by getSplits: " + splits.size() + ", TimeTaken: " + sw.now(TimeUnit.MILLISECONDS));
                            } 
 
                            return splits;
                        }

                        file = (FileStatus)var10.next();
                    } while(ignoreDirs && file.isDirectory());
					// 2.2 根据数据获取路径
                    Path path = file.getPath();
                    long length = file.getLen();
                    // 2.3 数据存在,开始处理数据
                    if (length != 0L) {
                        BlockLocation[] blkLocations;
                        // 获取数据位置
                        if (file instanceof LocatedFileStatus) {
                            blkLocations = ((LocatedFileStatus)file).getBlockLocations();
                        } else {
                            FileSystem fs = path.getFileSystem(job.getConfiguration());
                            blkLocations = fs.getFileBlockLocations(file, 0L, length);
                        }
                        //判断是否可以切 压缩文件不可以切,不可以切就直接当成一个片
                        if (this.isSplitable(job, path)) {
                        // 获取数据块大小和切片大小
						// 这里片大小是和最小尺寸最大尺寸相关 片尺寸默认为了1  因为如果是压缩文件,切片就需要解压缩,这样太过麻烦
						// 修改片大小 改大  将minSize改大    改小  将maxSize改小  也就是,反着改
						// Math.max(minSize, Math.min(maxSize, blockSize));
                            long blockSize = file.getBlockSize();
                            long splitSize = this.computeSplitSize(blockSize, minSize, maxSize);

                            long bytesRemaining; // 剩余大小
                            int blkIndex;
                            //  开始切片
                            //  只要大于1.1倍就可以切, 也就是,最后一块允许超出一点的,但不允许超出0.1 防止小文件出现
                            for(bytesRemaining = length; (double)bytesRemaining / (double)splitSize > 1.1; bytesRemaining -= splitSize) {
                            	
                                blkIndex = this.getBlockIndex(blkLocations, length - bytesRemaining);
                                splits.add(this.makeSplit(path, length - bytesRemaining, splitSize, blkLocations[blkIndex].getHosts(), blkLocations[blkIndex].getCachedHosts()));
                            } 
							// 最后一块收尾
                            if (bytesRemaining != 0L) {
                                blkIndex = this.getBlockIndex(blkLocations, length - bytesRemaining);
                                splits.add(this.makeSplit(path, length - bytesRemaining, bytesRemaining, blkLocations[blkIndex].getHosts(), blkLocations[blkIndex].getCachedHosts()));
                            }
                        } else {
                            if (LOG.isDebugEnabled() && length > Math.min(file.getBlockSize(), minSize)) {
                                LOG.debug("File is not splittable so no parallelization is possible: " + file.getPath());
                            }
							
                            splits.add(this.makeSplit(path, 0L, length, blkLocations[0].getHosts(), blkLocations[0].getCachedHosts()));
                        }
                    } else {
                        splits.add(this.makeSplit(path, 0L, length, new String[0]));
                    }
                }
            }
        }
    }
```java

3.总结

三步走

1.配置 获取元数据,配置相关数据

  • 1.配置最小片,最大片大小,
  • 2.配置是否需要忽略文件夹
  • 3.获取元数据

2.验证合法性(过滤)

  • 1.判断操作文件是否是文件夹并执行操作
  • 2.非空判断并获取数据块位置
  • 3.判断是否可切分,是压缩文件直接就按整片处理
  • 3.1不是压缩文件就切片
  • 3.2 切片注意大小
  • 3.3 最后收尾将最后一块处理掉(可超过不到0.1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值