Hadoop案例之自定义分片策略解决大量小文件问题

来源:互联网 发布:网络犯罪调查好看吗 编辑:程序博客网 时间:2024/05/22 13:12

Hadoop案例之自定义分片策略解决大量小文件问题

 

转载:

http://blog.csdn.net/qq1010885678/article/details/50771361

1.默认的分片策略TextInputFormat

应该都知道默认的TextInputFormat是一行行的读取文件内容,这对于一个或几个超大型的文件来说并没有什么问题,但是在实验读取大量小文件的时候,性能及其低下。

1.1实验过程

分别有5个文件夹,每个文件夹下有不同数量(1-2千个)的小文件(10+k大小),总量大概有8k+个文件,使用CLI命令上传到HDFS就花费了一个多小时

环境为本地电脑安装的伪分布式Hadoop集群,机器配置为四核I7CPU16GRAM

编写简单的worldCount程序,一切默认,放到集群上跑的时候出现以下情况:

1.启动的mapper总数量为8k+个!而一个节点能同时运行的mapper数量为
2.
整个map过程及其缓慢,50%跑了2h 
2.CPU
总用率高达80%,整个机器开始发出呲呲呲的声音

可见大量的小文件对mapreduce程序性能的影响有多大。

1.2问题的根本所在

HDFS上的文件是按block来存储的。

如果一个文件很大,超出了一个block的设定,那么它就会被划分为多个block存储,mapreduce程序读取时,每个block都会对应输入一个mapper,所以大文件,默认的分片策略是可以hold住的。

但是如果是很多小文件的话,每个小文件存储的时候都会是一个block,即使它很小,远远达不到block大小(默认128M),HDFS还是会将其存储在一个block中,那么问题就来了,默认的分片策略在读取这些小文件的时候,每个block都会产生一个mapper,所以就有了上面程序中出现了8k+mapper的情况。

1.3解决方案

既然知道了问题所在,那么就可以指定对应的解决方案,无非就是从两点入手:

1.默认每个小文件对应一个block,那么可以采取压缩等手段将多个小文件进行合并存储,以达到每个block存储的内容都是足够大的。 
2.
修改mapreduce默认的分片策略,使得读取文件进行分片的时候让每个block可以对应多个小文件,而不再是仅仅一个小文件。

 

2.自定义的分片策略MyInputFormat

关于HadoopInputFormat类,网上有很多详细介绍的文章,默认的分片策略使用的就是其TextInputFormat子类,这里将介绍另外一个子类:CombineFileInputFormat

顾名思义,CombineFileInputFormat是用来将输入的小文件进行合并,然后输入到一个mapper中的策略。 
这是一个抽象类,只实现了InputFomat接口的getSplit方法。(P.S.所有的分片策略都要继承InputFormat,并实现getSplitcreateRecordReader两个方法 
既然我们需要用到CombineFileInputFormat,但他留了一个接口方法让我们实现,那么就可以自定义一个MyInputFormat类继承自CombineFileInputFormat,重写createRecordReader

关于InputFormat接口的两个方法:

1.getSplit是从HDFS上读取文件,并形成逻辑的分片,在本文中,这个分片会包含多个小文件 
2.createRecordReader
会创建一个RecordReader对象,用来读取getSplit产生的分片mapper中的键值对就是这个RecordReader输出的。

之前讨论到的自定义MyInputFormat类实现分片策略,但是分片之后如何读取分片内的数据是createRecordReader方法创建的RecordReader对象决定的

所以自定义分片策略的关键在于两点:

1.MyInputFormat类自定义分片策略 
2.MyRecordReader
类自定义读取分片内的数据

 

 

4.源码地址

github源码 

0 0