上一节中提到的方案均需要用户自己编写程序,每隔一段时间对小文件进行merge以便减少小文件数量。那么能不能直接将小文件处理模块嵌到HDFS中,以便自动识别用户上传的小文件,然后自动对它们进行merge呢?
本节介绍了两篇论文针试图在系统层面解决HDFS小文件问题。这两篇论文对不同的应用提出了解决方案,实际上思路类似:在原有HDFS基础上添加一个小文件处理模块,当一个文件到达时,判断该文件是否属于小文件,如果是,则交给小文件处理模块处理,否则,交给通用文件处理模块处理。小文件处理模块的设计思想是,先将很多小文件合并成一个大文件,然后为这些小文件建立索引,以便进行快速存取和访问。
论文[4]针对WebGIS系统的特点提出了解决HDFS小文件存储的方案。WebGIS是结合web和地理信息系统(GIS)而诞生的一种新系统。在WebGIS中,为了使浏览器和服务器之间传输的数据量尽可能地少,数据通常被切分成KB的小文件存储在分布式文件系统中。论文结合WebGIS中数据相关性特征,将保存相邻地理位置信息的小文件合并成一个大的文件,并为这些小文件建立索引以便对小文件进行存取。(n*n)
该论文将size小于16MB的文件当做小文件,需将它们合并成64MB(默认的block size),并建立索引,索引结构和文件存储方式见上图。索引方式是一般的定长hash索引。
论文[5]针对Bluesky系统的特点提出了解决HDFS小文件存储的方案。Bluesky是中国电子教学共享系统,里面的ppt文件和视频均存放在HDFS上。该系统的每个课件由一个ppt文件和几张该ppt文件的预览快照组成。当用户请求某页ppt时,其他相关的ppt可能在接下来的时间内也会被查看,因而文件的访问具有相关性和本地性。本文主要有2个idea:第一,将属于同一个课件的文件合并成一个大文件,以提高小文件存储效率。第二,提出了一种two-level prefetching机制以提高小文件读取效率,即索引文件预取和数据文件预取。索引文件预取是指当用户访问某个文件时,该文件所在的block对应的索引文件被加载到内存中,这样,用户访问这些文件时不必再与namenode交互了。数据文件预取是指用户访问某个文件时,将该文件所在课件中的所有文件加载到内存中,这样,如果用户继续访问其他文件,速度会明显提高。
下图展示的是在BlueSky中上传文件的过程:
下图展示的是在BlueSky中阅览文件的过程:
5、 总结
Hadoop目前还没有一个系统级的通用的解决HDFS小文件问题的方案。它自带的三种方案,包括Hadoop Archive,Sequence file和CombineFileInputFormat,需要用户根据自己的需要编写程序解决小文件问题;而第四节提到的论文均是针对特殊应用提出的解决方案,没有形成一个比较通用的技术方案。
更多Hadoop相关信息见Hadoop 专题页面 ?tid=13