海量小文件(LOSF,lots of small files)的存储是很多公司都遇到的难题,不管是互联网公司(如社交网站)还是传统的IT企业(如医疗IT的PACS厂商),都会遇到这个难题。
问题的根源在与,无论是文件系统还是网络传输,小文件都需要很多额外操作,如
1、数据布局没有优化,寻址次数大大增加,寻道时间及旋转延迟大大增加,从而每秒的输入输出量 (IOPS,Input/Output Per Second) 、数据吞吐量(Throughput)都明显下降
其实很简单,大家考虑下,拷贝一个1G的文件,和拷贝一个都是零散文件的1G文件夹,其速度差距如何,就清楚了
2、网络通信开销增加,网络延迟变大
其实很简单,大家考虑下,网络传一个1G的文件,和传一个都是零散文件的1G文件夹,其速度差距如何,就清楚了
3、分布式存储,网络交互次数增加,数据存储位置频繁变化,网络通信增加,速度变慢
其实也不难,比如,从一个服务器上拉取10000个文件,与从10个服务器上拉取10000个文件(每次都要问下,下一个文件存储在那个服务器上),谁快谁慢,就清楚了
大家应对这个问题时,采用的方法无非是4种:
1、砸硬件,用硬件性能提升,让传输效率提供
2、用缓存,通过缓存,减少磁盘访问次数,减少交互环节,提高传输效率
3、改变存储策略
4、减少询问次数,比如一次通信,找到1000个文件的地址,400个在服务器A,600个在服务器B,不按文件顺序,而是先从A取400个,再从B取600个,通信就会减少很多,速度就会有所提升(但业务场景要合适才行)
这里主要说一下第3点。
传输一个都是零散文件的1G文件夹时,我们可以这样做,先压缩一下,然后再传递,再解压,发现很多时候居然会节约时间。
也就是说:
压缩+传输压缩文件+解压用的时间 < 直接读取并传送零散文件的时间
但如果直接存储压缩文件,那压缩我们只需要上传时做一次,平时读取时,其实为:
传输+解压用的时间 < 压缩+传输传输压缩文件+解压用的时间 < 直接传送零散文件的时间
那如果压缩和解压的时候,我们只做归档,不做压缩岂不是更节约时间?
传输+归档读取用的时间 < 传输+解压用的时间 < 直接传送零散文件的时间
恩,对了,其实大家的解决方案就是,将大量小文件,写到一个大文件里,这样读取效率就飞一样上来了。
无论是Facebook的Haystack还是淘宝的TFS,用的都是类似的方案。(实际上要复杂的多,请参考论文”Finding a needle in Haystack:Facebook’s photo storage”)
那HDFS呢?当然也支持咯,但要写代码处理一下,大家可以自行找一下Hadoop Archive, Sequence file, CombineFileInputFormat等。