您的位置:首页 > 运维架构

hadoop处理小文件问题

2015-04-22 16:45 169 查看
本文转自个人原创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测试程序

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public
class
TestSmallFiles
{




public
static
class
Map
extends
Mapper<Object,
Text,
Text,
Text>
{



public
void
map(Object
key,
Text
value,
Context
ctx)
throws
IOException,
InterruptedException
{





}


}




public
static
void
main(String[]
args)
throws
IOException,
InterruptedException,
ClassNotFoundException
{





Configuration
conf
=
new
Configuration();



Job
job
=
new
Job(conf,
"TestSmallFiles");



job.setJarByClass(TestSmallFiles.class);



job.setInputFormatClass(TextInputFormat.class);



job.setOutputFormatClass(TextOutputFormat.class);



FileInputFormat.addInputPath(job,
new
Path(args[0]));



FileOutputFormat.setOutputPath(job,
new
Path(args[1]));



job.setMapperClass(Map.class);



job.setMapOutputKeyClass(Text.class);



job.setMapOutputValueClass(Text.class);



System.exit(job.waitForCompletion(true)
?
0
:
1);


}

}

上面这个程序只有一个空的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

运行后通过可视化界面查看Job执行状态,如下截图





我们可以看到启动了24个Map tasks,因为这个分区下有24个文件。

第四步,测试archive文件

hadoop jar ./javali.jar org.javali.mr.test.TestSmallFiles /tmp/smallFiles.har /tmp/result1

运行后同样跟踪Job的执行状态





我们看到这次只启动了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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: