hadoop中map分片信息的源码分析

之前大家对于hadoop中map输入的分片不是很了解,直接认为map输入的分片数是由文件的个数和是否大于block_size来决定map的个数,这样是不准确的,的确在默认的情况下是这样的,但是实际优化过程中,并不是文件越多就起的map就越多,因为小文件太多的话,这样处理会影响系统效率,当然大文件的切分也不一定是按照block_size来切分,今天我们主要看看小文件合并的类CombineFileInputFormat中和切分大文件的FileInputFormat类

1.先看FileInputFormat类
其切分的方法如下:

 public List<InputSplit> getSplits(JobContext job) throws IOException {
        StopWatch sw = (new StopWatch()).start();//这是监控任务用的
  /*这两个值可以通过mapred.min.split和mapred.max.split.size来设置
        其中minSize是从1和你设置的mapred.min.split中最大值*/
        long minSize = Math.max(this.getFormatMinSplitSize(), getMinSplitSize(job)); 
        long maxSize = getMaxSplitSize(job);
        List<InputSplit> splits = new ArrayList();//存储得到的分片结果
        List<FileStatus> files = this.listStatus(job);//存储着输入文件列表信息
        Iterator i$ = files.iterator(); //创建一个用来遍历文件的迭代器

        while(true) {
            while(true) {
                while(i$.hasNext()) {
                    FileStatus file = (FileStatus)i$.next();
                    Path path = file.getPath();
                    long length = file.getLen();//该文件长度
                    if(length != 0L) {
                        BlockLocation[] blkLocations; 
                        //判断是否是本节点路径下的file
                        if(file instanceof LocatedFileStatus) {
                            blkLocations = ((LocatedFileStatus)file).getBlockLocations();//读取文件所属block的位置
                        } else {
                            FileSystem fs = path.getFileSystem(job.getConfiguration());//从别的节点上去读取文件位置
                            blkLocations = fs.getFileBlockLocations(file, 0L, length);
                        }
            //判断文件是否可分割,如果是压缩的,将不可分割
                        if(this.isSplitable(job, path)) {
                            long blockSize = file.getBlockSize();  //获取当前block_size大小,默认128M
                            /*这里是关键,splitSize是由blockSize,minSize,maxSize共同确定的,这里的computeSplitSize()方法其具体实现方式是return Math.max(minSize, Math.min(maxSize, blockSize));也就是maxSize和blockSize的最小值与minSize的最大值就是splitSize*/
                            long splitSize = this.computeSplitSize(blockSize, minSize, maxSize);
                            long bytesRemaining;//分好片的剩余字节数
                            int blkIndex;
                            //当剩余数据分片大小与分片大小比值大于1.1时,继续分片,小于时停止分片
                            for(bytesRemaining = length; (double)bytesRemaining / (double)splitSize > 1.1D; bytesRemaining -= splitSize) {
                                blkIndex = this.getBlockIndex(blkLocations, length - bytesRemaining);
                                splits.add(this.makeSplit(path, length - bytesRemaining, splitSize, blkLocations[blkIndex].getHosts(), blkLocations[blkIndex].getCachedHosts()));
                            }
        //如果余下的数据小于一个splitSize就独自是一个分片
                            if(bytesRemaining != 0L) {
                                blkIndex = this.getBlockIndex(blkLocations, length - bytesRemaining);
                                splits.add(this.makeSplit(path, length - bytesRemaining, bytesRemaining, blkLocations[blkIndex].getHosts(), blkLocations[blkIndex].getCachedHosts()));
                            }
                        } else {
  
  //不可压缩就返回整块数据
                            splits.add(this.makeSplit(path, 0L, length, blkLocations[0].getHosts(), blkLocations[0].getCachedHosts()));
                        }
                    } else {
                    //对于文件长度为0时,返回一个空的split
                        splits.add(this.makeSplit(path, 0L, length, new String[0]));
                    }
                }

                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;
            }
        }
    }

这里可以看出大文件分片的原理,一般可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值