本文转自个人原创blog: http://www.javali.org/document/hadoop-handle-numerous-small-files.html
Hadoop带来了廉价的处理大数据的能力,可以这么理解,hadoop是为了解决大数据(大文件)计算而出现的分布式计算框架,不过对于小文件(指远小于block size,默认64M)却会存在各种问题,比如:过多的消耗namenode的内存(一个文件在namenode会占用150Bytes内存,如果存在海量小文件,必然会超出计算机存储的极限);另外计算时启动过多的Map Tasks,占用过多资源以至于降低计算效率。
问题背景
有时由于业务需要,Hadoop不可避免的会存储大量的小文件,我有一个分时计算的业务,每天会产生24个文件;纠结的是,计算当前小时数据依赖所有的历史数据,而实际上每个文件不到1M大小,Job会为每一个文件启动一个Map task,而每 一个 map task都仅仅处理了非常小的 数据,我们都知道,Map Task都需要消耗一定的资源。随着时间推移,每次运行Job启动的Map tasks越来越多,运行效率也随之降低。
这张截图就是我的Job优化前的执行状态,它启动了2273个Map tasks,整个Map阶段耗时4分多钟,完成Job计算需要7分钟,对于实时性的计算需求,这种计算耗时是很不理想的
解决办法
我们知道了问题在哪里,如何解决呢?
幸运的是,由于这类问题存在的普遍性,hadoop引入了archives即HAR files(0.18.0版),使用方法可以看这里。
接下来我们做个测试,看Hadoop archives能否解决我们面临的问题。
第一步: 我们把2012-11-01一天共计24个文件打包成HAR文件,放置到/tmp目录
hadoop archive -archiveName smallFiles.har -p /user/hive/warehouse/promotion_hour_bind/dt=2012-11-01/hour=*/tmp/
第二步:写一个最简单的MapReduce测试程序
上面这个程序只有一个空的Map函数,我们只需要测试打har包前后启动的Map tasks数,不需要任何其他的逻辑。接下来把类打成jar包(javali.jar)上传到服务器
第三步,测试未打archive的源文件,看执行情况
hadoop jar ./javali.jar org.javali.mr.test.TestSmallFiles /user/hive/warehouse/promotion_hour_bind/dt=2012-11-01/*/* /tmp/result0
hadoop jar ./javali.jar org.javali.mr.test.TestSmallFiles /tmp/smallFiles.har /tmp/result1
我们看到这次只启动了1个map task,减少了23个Map tasks启动所需的资源
结论
至此,我们不难发现,hadoop archive能很好的解决海量小文件带来的问题:极大的减少了namenode的内存消耗,同时减少了job执行时启动的Map tasks,计算性能得到了极大的提升——优化后的Map耗时降到了1分钟左右。
我们清楚的知道hadoop archive是把物理上的多个小文件抽象成逻辑上的一个文件,实际上海量小文件依然是物理存在的,启动的Map tasks数量虽然减少了,但不可避免的还要多次去获取这些文件,即获取文件的次数没有减少,copy阶段同样会消耗过多的资源。
我们可以把多个文件合并成1个物理文件,前提是不影响业务的处理,可以预想这么做能提升计算效率,同时也引入了风险因素(打har包同样也会),这时候就需要根据实际情况权衡采用何种方案了
『完』
参考: http://blog.cloudera.com/blog/2009/02/the-small-files-problem/
本文探讨了Hadoop在处理大量小文件时遇到的问题,包括消耗NameNode内存和启动过多Map任务导致效率下降。通过引入HAR文件(Hadoop Archives)进行文件打包,成功减少了Map任务数量,显著提升了计算性能。然而,虽然优化了Map阶段,但在Copy阶段仍存在资源消耗。文章建议在不影响业务的情况下,考虑将小文件合并以进一步提高效率。




被折叠的 条评论
为什么被折叠?



