大数据学习-Hadoop-FileInputFormat源码分析

本片文章开始整理FileInputFormat切片源码解析(input.getSplits(job))的学习笔记

获取切片的代码流程

  1. 设置minSize的初始值,做法是取最小切片的大小和配置切片的最小值中的最大值作为minSize
  2. 设置maxSize -> 取最大切片值
  3. 创建一个切片的集合
  4. 获取要进行切片的输入目录
  5. 遍历输入目录
    1. 获取文件路径
    2. 获取文件长度
    3. 如果文件的长度不为零,就进行切片操作,如果为零,就向切片的集合添加一个零长度的文件
      1. 先判断要切片的文件是否在本地还是网络,如果是网络的就直接获取块的位置信息,如果是本地的,就要获取块的本地信息,外加文件的长度
      2. 然后进行判断是否是可以进行切片
      3. 如果可以切片
        1. 先获取文件的块大小
        2. 计算切片的大小

        Math.max(minSize, Math.min(maxSize, blockSize));

        1. 然后对文件进行切片,将切的片放入切片集合中
      4. 如果不可以切片,就直接将文件的所有放入切片集合中
  6. 返回切片集合

getSplits源码解析

public List<InputSplit> getSplits(JobContext job) throws IOException {
	// 开启一个计时器,计时的单位是纳秒
    StopWatch sw = new StopWatch().start();
    // 设置minSize的初始值,做法是取最小切片的大小和配置切片的最小值中的最大值作为minSize
    long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));
    // 设置maxSize -> 取最大切片值
    long maxSize = getMaxSplitSize(job);

    // 创建切片
    List<InputSplit> splits = new ArrayList<InputSplit>();
    // 获取输入目录(可以含有正则表达式匹配的目录)
    List<FileStatus> files = listStatus(job);
    for (FileStatus file: files) {
    	// 获取文件路径
      Path path = file.getPath();
      // 获取文件长度
      long length = file.getLen();
      if (length != 0) {
      //表示块的网络位置,有关包含块副本的主机*的信息以及其他块元数据(例如,文件*与该块关联的偏移量,长度,是否损坏等)。
        BlockLocation[] blkLocations;
        if (file instanceof LocatedFileStatus) {
          blkLocations = ((LocatedFileStatus) file).getBlockLocations();
        } else {
          FileSystem fs = path.getFileSystem(job.getConfiguration());
          blkLocations = fs.getFileBlockLocations(file, 0, length);
        }
        if (isSplitable(job, path)) {
          // 获取文件的块大小
          long blockSize = file.getBlockSize();
          // ☆ 重点!!!! 计算切片的大小
          long splitSize = computeSplitSize(blockSize, minSize, maxSize);
		
          long bytesRemaining = length;
          while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {
          	// 获取块的索引大小
            int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
            			// 使用主机和缓存块信息构造一个切片
            splits.add(makeSplit(path, length-bytesRemaining, splitSize,
                        blkLocations[blkIndex].getHosts(),
                        blkLocations[blkIndex].getCachedHosts()));
            bytesRemaining -= splitSize;
          }

          if (bytesRemaining != 0) {
            int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
            splits.add(makeSplit(path, length-bytesRemaining, bytesRemaining,
                       blkLocations[blkIndex].getHosts(),
                       blkLocations[blkIndex].getCachedHosts()));
          }
        } else { 
          // 如果设置为不可切片的话就直接将文件的全部放入切片
          splits.add(makeSplit(path, 0, length, blkLocations[0].getHosts(),
                      blkLocations[0].getCachedHosts()));
        }
      } else { 
        // 创建一个空的主机列表(包含0长度的文件)
        splits.add(makeSplit(path, 0, length, new String[0]));
      }
    }
    // 保存输入文件的数量和长度以用于度量标准/ 负载均衡
    job.getConfiguration().setLong(NUM_INPUT_FILES, files.size());
    // 停止计时
    sw.stop();
    // 返回切片信息
    return splits;
  }

computeSplitSize源码解析

重点!这个代码是计算切片大小的,算法就是取最小长度和(最大长度和块的长度)的最小值的最大值,但是一般取得就是配置文件中的块的长度,在hadoop 1.X时代是64M,在hadoop 2.X时代是128M,但是运行在local中的时候默认为32M

protected long computeSplitSize(long blockSize, long minSize,
                                  long maxSize) {
    return Math.max(minSize, Math.min(maxSize, blockSize));
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值