Hadoop适用于少量的大文件场景,而不是大量的小文件场景(这里的小文件通常指文件大小显著小于HDFS Block Size的文件),其主要原因是因为FileInputFormat在为这些小文件生成切片的时候,会为每一个小文件生成一个切片,如果小文件数目众多,会导致大量的Map Task,每个Map Task仅仅处理很少量的数据(即一个小文件的全部数据),这种情况会带来很大的运行开销且耗时较长。
 
CombineFileInputFormat设计目的就是用来应对小文件的场景,FileInputFormat为每一个小文件生成一个切片,而CombineFileInputFormat会将许多小文件“打包”为一个切片,使得每一个Map Task可以处理更多的数据。更为关键的是CombineFileInputFormat在决定将哪些小文件的数据块“打包”为一个切片时会充分考虑数据本地性(节点本地性、机器本地性)的特性,因此不会在运行时间和网络带宽方面来很大的开销。
 
不光是小文件的场景,在处理大文件时CombineFileInputFormat也有优势,原因在于它会将同一节点上的多个数据块形成一个切片,对Data-Local Map Tasks可能带来一定的优化。
 
思路
 
CombineFileInputFormat有三个重要的属性:
 
 
maxSplitSize:切片大小最大值,可通过属性mapreduce.input.fileinputformat.split.maxsize或CombineFileInputFormat实例方法setMaxSplitSize()进行设置;
 
minSplitSizeNode:同一节点的数据块形成切片时,切片大小的最小值,可通过属性mapreduce.input.fileinputformat.split.minsize.per.node或CombineFileInputFormat实例方法setMinSplitSizeNode()进行设置;
 
minSplitSizeRack:同一机架的数据块形成切片时,切片大小的最小值,可通过属性mapreduce.input.fileinputformat.split.minsize.per.rack或CombineFileInputFormat实例方法setMinSplitSizeRack()进行设置;
 
 
CombineFileInputFormat有一个“过滤池”的概念,pools中保存着多个“过滤池”实例(实际就是MultiPathFilter实例,该实例由多个PathFilter实例构成),一个切片中的数据块只可能来自于同一个过滤池,但可以来自同一个过滤池中的不同文件。
 
注:“过滤池”的设计目的还不是很明白,欢迎大家交流,貌似Hive有相关的应用。
 
getSplits():
 
 
step 1
 
获取输入路径中的所有文件;
 
step 2
 
迭代为每个过滤池中的文件生成切片;
 
     step 2.1
     
     获取满足当前过滤池实例的所有文件myPaths;
 
     step 2.2
 
     为mypaths中的文件生成切片;
 
step 3
 
为不属于任何过滤池的文件生成切片。
 
无论是满足某过滤池实例条件的文件还是不属于任何过滤池的文件,可以笼统地理解为“一批文件”,getMoreSplits()就是为这一批文件生成切片的。
 
 
step 1
 
前面提到,CombineFileInputFormat在将小文件“打包”为一个切片的时候,会考虑数据本地性(节点本地性、数据本地性),而且一个切片涉及到多个小文件,因此此处定义了三个对应关系:
 
rackToBlocks:机架和数据块的对应关系;
blockToNodes:数据块和节点的对应关系;
nodeToBlocks:节点和数据块的对应关系。
 
此外还应注意到比较重要的两个类:
 
OneFileInfo:代表一个文件;
OneBlockInfo:代表一个文件中的数据块,注意这个地方的数据块是“逻辑”上的数据块,不能直接对应HDFS Block,后续会说原因。
 
step 2
 
迭代这“一批文件”,为每一个文件构建OneFileInfo对象(由OneFileInfo构造函数完成),OneFileInfo对象本身并没有多少实际作用,它的意义是在构建过程中维护了上述三个对应关系的信息。
 
其中有一段代码是为这个文件生成对应的OneBlockInfo对象(多个),如下:
 
 
可以看出,对于每一个数据块(由locations[i]表示)而言,构建OneBlockInfo的逻辑是一个循环的过程,根据maxSize(maxSplitSize)的值不同就有可以产生多个OneBlockInfo对象,这也是“逻辑块”的原因。
 
迭代完成之后,我们即可以认为数据块、节点、机架相互之间的对应关系已经建立完毕,接下来可以根据这些信息生成切片。
 
step 3 
 
切片的形成过程(createSplits())如下:
 
(1)不断迭代节点列表,逐个节点(数据块)形成切片(Local Split);对于每一个节点而言,遍历并累加这个节点上的数据块,
     a.如果maxSplitSize != 0且累加的数据块大小大于或等于maxSize,则将这些数据块形成一个切片,继续下一个节点(为了达到多个节点之间分布切片的目的);
     b.如果maxSplitSize == 0,则上述累加的数据块可能为该节点的全部数据块,也可能是节点在迭代过程中剩余的数据块,这些数据块根据条件的不同可能全部形成一个切片,或者全部留作后续处理;
 
(2)不断迭代机架列表,逐个机架(数据块)形成切片(Rack Split);对于每一个机架而言,处理流程与(1)类同,仅判断条件时策略不同;
     
(3)遍历并累加剩余数据块,如果maxSplitSize != 0且累积的数据块大小大于或等于maxSplitSize,则将这些数据块形成一个切片;
 
(4)剩余数据块形成一个切片。
 
该部分代码比较冗长,建议读者自行阅读,核心逻辑比较简单:优先将一个节点上的数据块形成切片(同时兼顾切片分布问题),次之将一个机架的数据块形成切片,最后将剩余数据块形成切片。

Hadoop CombineFileInputFormat实现原理及源码分析的更多相关文章

  1. Hadoop FileInputFormat实现原理及源码分析

    FileInputFormat(org.apache.hadoop.mapreduce.lib.input.FileInputFormat)是专门针对文件类型的数据源而设计的,也是一个抽象类,它提供两 ...

  2. OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

    http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...

  3. ConcurrentHashMap实现原理及源码分析

    ConcurrentHashMap实现原理 ConcurrentHashMap源码分析 总结 ConcurrentHashMap是Java并发包中提供的一个线程安全且高效的HashMap实现(若对Ha ...

  4. HashMap和ConcurrentHashMap实现原理及源码分析

    HashMap实现原理及源码分析 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表, ...

  5. (转)ReentrantLock实现原理及源码分析

    背景:ReetrantLock底层是基于AQS实现的(CAS+CHL),有公平和非公平两种区别. 这种底层机制,很有必要通过跟踪源码来进行分析. 参考 ReentrantLock实现原理及源码分析 源 ...

  6. 【转】HashMap实现原理及源码分析

    哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景极其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出 ...

  7. 【OpenCV】SIFT原理与源码分析:DoG尺度空间构造

    原文地址:http://blog.csdn.net/xiaowei_cqu/article/details/8067881 尺度空间理论   自然界中的物体随着观测尺度不同有不同的表现形态.例如我们形 ...

  8. 《深入探索Netty原理及源码分析》文集小结

    <深入探索Netty原理及源码分析>文集小结 https://www.jianshu.com/p/239a196152de

  9. HashMap实现原理及源码分析之JDK8

    继续上回HashMap的学习 HashMap实现原理及源码分析之JDK7 转载 Java8源码-HashMap  基于JDK8的HashMap源码解析  [jdk1.8]HashMap源码分析 一.H ...

随机推荐

  1. Android技术精髓-Bitmap详解

    Bitmap (android.graphics.Bitmap) Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保 ...

  2. PHP数据结构预热:PHP的迭代器(转)

    迭代器有时又称光标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如list或vector)上遍访的接口,设计人员无需关心容器物件的内容. 各种语言实作Iterator的 ...

  3. Android Rom修改

    最近项目里要实现修改开机动画 屏蔽系统桌面等一些涉及到修改底层的功能 一开始研究了一番 心想着看来这是要定制系统 做rom开发了 所以就牛逼哄哄的跑去下源码 研究rom开发 后来发现这将是一个庞大的工 ...

  4. ubuntu vim YouComlpeteMe配置

    使用vundle安装时,在.vimrc中添加 Plugin 'Valloric/YouCompleteMe' 使用Bundle会安装失败原因未知 YCM编译时附加选项--system-libclang ...

  5. NSPredicate查询日期的问题

    查询日期的时候日期可以根据参数传进去,但不能在字符串中传参后在作为查询条件 简单比较以下两段代码 NSDate* date1=[NSDate date]; NSDate* date2=date1; r ...

  6. 得于吾师傅的js知识 js类,单写模板,和私有保护的方法

    js的类的写法: 1,写法一:function内部包含this.function()如代码: var origin_class = function(name) { var lover = ''; t ...

  7. css 圆角效果

    http://intacto10years.com/index_start.php<div style="width:800px; height:1300px;">&l ...

  8. 启动php-fpm时报错

    [root@localhost ~]# /usr/local/php/sbin/php-fpm [06-Aug-2012 19:17:53] ALERT: [pool www] pm.min_spar ...

  9. iOS视图控制对象生命周期-init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear的区别及用途

    init-初始化程序 viewDidLoad-加载视图 viewWillAppear-UIViewController对象的视图即将加入窗口时调用: viewDidApper-UIViewContro ...

  10. IntelliJ IDEA提示忽略大小写

    1.打开设置(CTRL+ALT+S) 2.搜索Code Completion,点击Case sensitive completion后面的选择框,选中None