搜索
查看: 12510|: 4

求点大量小文件存储的资料

[复制链接]

1

主题

0

回帖

15

积分

新手上路

积分
15
发表于 2014-1-17 16:33:29 | 显示全部楼层 |阅读模式
如题,现在考虑的是hadoop,知道hadoop是专为大文件设计的,但是没有别的办法。
希望吧主给点资料学习下吧

152

主题

47

回帖

3015

积分

管理员

积分
3015
发表于 2014-1-18 01:40:43 | 显示全部楼层
网上找了点资料仅供参考:
名称:Hadoop关于处理大量小文件的问题和解决方法
摘要:
小文件指的是那些size比HDFS 的block size(默认64M)小的多的文件。如果在HDFS中存储小文件,那么在HDFS中肯定会含有许许多多这样的小文件(不然就不会用hadoop了)。
而HDFS的问题在于无法很有效的处理大量小文件。

任何一个文件,目录和block,在HDFS中都会被表示为一个object存储在namenode的内存中,没一个object占用150 bytes的内存空间。所以,如果有10million个文件,
没一个文件对应一个block,那么就将要消耗namenode 3G的内存来保存这些block的信息。如果规模再大一些,那么将会超出现阶段计算机硬件所能满足的极限。

不仅如此,HDFS并不是为了有效的处理大量小文件而存在的。它主要是为了流式的访问大文件而设计的。对小文件的读取通常会造成大量从
datanode到datanode的seeks和hopping来retrieve文件,而这样是非常的低效的一种访问方式。

点我下载

欢迎关注我的微信公共账号:bigdata_cn
大数据中国(http://www.bigdatas.cn),以数据的力量改变生活!

152

主题

47

回帖

3015

积分

管理员

积分
3015
发表于 2014-1-18 01:52:02 | 显示全部楼层
还有人这样说:Hadoop不适合大量小文件存储的证实         
今天应邀测试。由于带宽影响,先测试上传小文件的性能。
发现上传一 252 字节的文件,当连接数不到50时,最高每秒能写入约300个文件。
Hadoop默认的块大小为64MB,由于本次测试为小文件。特此将块大小修改为512KB。
测试结果:
当连接数增多时,NameNode性能显著下降。使用iostat可以看到磁盘队列偶尔飙得老高,磁盘使用率接近100%。
随即查看系统资源使用情况:

Hadoop的存储性能

Hadoop的存储性能

附测试代码如下:
  1. import java.io.*;
  2. import java.util.UUID;
  3. import java.net.URI;
  4. import org.apache.hadoop.conf.Configuration;
  5. import org.apache.hadoop.fs.*;
  6. import lrapi.lr;

  7. public class Actions{
  8.      public static FileSystem fs;
  9.      public int init() throws Throwable{
  10.          fs=FileSystem.get(new URI("hdfs://192.168.10.31:9000"),new Configuration());
  11.          return 0;
  12.      }//end of init

  13.      public int action() throws Throwable{           
  14.          lr.start_transaction("WirteFile");
  15.          String fileName=UUID.randomUUID().toString().replace("-","");
  16.          String dirName=fileName.substring(0,2);

  17.          writeFile("/test/"+dirName+"/"+fileName
  18.                ,"c:/monitor/clear.bat");
  19.   
  20.          lr.end_transaction("WirteFile",lr.AUTO);
  21.          return 0;
  22.      }//end of action

  23.      public static boolean writeFile(String hdfsPath,String localFile){
  24.          try{
  25.              Filefile=new File(localFile);
  26.              BufferedInputStream inputStream=new BufferedInputStream(new FileInputStream(file));
  27.              Path hdfsPathDir=new Path(hdfsPath);
  28.              if(!fs.exists(hdfsPathDir.getParent()))
  29.                  fs.mkdirs(hdfsPathDir.getParent());
  30.              FSDataOutputStream out = fs.create(hdfsPathDir,true);
  31.              int len;
  32.              byte[] data=new byte[2048];
  33.              while((len=inputStream.read(data))!=-1){
  34.                  out.write(data,0,len);
  35.              }
  36.              out.flush();
  37.              out.close();
  38.              inputStream.close();
  39.          }catch (Exceptione) {
  40.              e.printStackTrace();
  41.              return false;
  42.          }
  43.          return true;
  44.      }

  45.      public int end() throws Throwable{
  46.          fs.close();
  47.          return 0;
  48.      }//end of end
  49. }
复制代码

只需附加 commons-logging-1.0.4.jar 、 hadoop-0.20.2-core.jar 资源。
从IO写入次数可看出,写次数非常高。而且写次数速度和每秒上传的速度基本是相当的,并未进行有效的合并写入。也就是说Hadoop对小文件的写入没有作任何优化,至此即可证明Hadoop不适合大量小文件的存储。存储类产品多少都存在小文件的优化问题,小文件需要更新更多的源信息,需要更多的IO操作。
(注:写入Hadoop的文件名为UUID,文件存入在以UUID首两个字母的子文件夹中。避免单文件数量过多时对性能的影响)


大数据中国(http://www.bigdatas.cn),以数据的力量改变生活!

152

主题

47

回帖

3015

积分

管理员

积分
3015
发表于 2014-1-18 02:01:25 | 显示全部楼层
有人这样问:Hadoop为什么处理小数据量时效果不好?
权威指南的原话:
As a rule of thumb, each file, directory, and block takes about 150 bytes. So, for example,
if you had one million files, each taking one block, you would need at least
300 MB of memory.

hadoop处理大量小数据文件效果不好。

hadoop对数据的处理是分块处理的,默认是64M分为一个数据块,如果存在大量小数据文件(例如:2-3M一个的文件)这样的小数据文件远远不到一个数据块的大小就要按一个数据块来进行处理。
这样处理带来的后果由两个:1.存储大量小文件占据存储空间,致使存储效率不高检索速度也比大文件慢。
2.在进行MapReduce运算的时候这样的小文件消费计算能力,默认是按块来分配Map任务的(这个应该是使用小文件的主要缺点)

那么如何解决这个问题呢?
1.使用Hadoop提供的Har文件,Hadoop命令手册中有可以对小文件进行归档。
2.自己对数据进行处理,把若干小文件存储成超过64M的大文件。

hadoop 针对大块数据、流式处理
小文件: 网络、IO的开销与文件本身传输的开销比重太大,如果大文件就不一样了
SequeceFile是Hadoop API提供的一种二进制文件支持。这种二进制文件直接将<key, value>对序列化到文件中。一般对小文件可以使用这种文件合并,即将文件名作为key,文件内容作为value序列化到大文件中。这种文件格式有以下好处:
支持压缩,且可定制为基于Record或Block压缩(Block级压缩性能较优)
本地化任务支持:因为文件可以被切分,因此MapReduce任务时数据的本地化情况应该是非常好的。
难度低:因为是Hadoop框架提供的API,业务逻辑侧的修改比较简单。
坏处是需要一个合并文件的过程,且合并后的文件将不方便查看。

除了 小文件会占用太多NN的元数据存储外,过多的小文件会产生更多的小任务,任务上下文切换时间过多,CPU等资源利用也不足,整理计算性能会大大降低.
大数据中国(http://www.bigdatas.cn),以数据的力量改变生活!

152

主题

47

回帖

3015

积分

管理员

积分
3015
发表于 2014-1-18 02:09:31 | 显示全部楼层
有一篇这样的文章:Hadoop Archive解决海量小文件存储
这段时间看了公司部门邮件中大家讨论较多的几个关于HDFS的问题,一个是关于Namenode可扩展性的讨论,目前单台服务器作为Namenode,当文件数量规模不断增大时,元数据的规模增长将是一个需要面对的问题,由于Namenode需要将所有元数据Load到内存中,单台Namenode可能会无法管理海量的元数据。另一个是HDFS中SequenceFile存储方式的讨论,利用Block压缩方式可以很好的解决空间压力。

今天刚好看到Yahoo! Hadoop Blog上的一篇文章Hadoop Archive: File Compaction for HDFS和上面两个问题都有一点联系,文章主要提出了在HDFS中存在海量的小文件时,会给存储带来的一系列问题 。

HDFS中文件是按Block来存储的,默认一个Block的长度是128MB,当HDFS中存在大量小文件(长度小于128MB)时,不仅占用大量存储空间,而且也占用大量的namespace,给Namenode带来了内存压力,Yahoo内部有一个生产集群,统计下来有57,000,000个小于128MB的文件,这些小文件消耗了95%的namespace,占用了30%的存储空间。Namenode的压力一般也常常是因为有海量的小文件存在,如果没有这些小文件存在的话,Namenode内存还没撑爆,估计存储空间就先爆了。。

文中提到了解决方法,是利用Hadoop Archive(HAR),这个特性从Hadoop 0.18.0版本就已经引入了,他可以将众多小文件打包成一个大文件进行存储,并且打包后原来的文件仍然可以通过Map-reduce进行操作,打包后的文件由索引和存储两大部分组成,索引部分记录了原有的目录结构和文件状态。

har.png
举个例子,原本获取一个文件通过命令
  1. hadoop fs –get hdfs://namenode/foo/file-1 localdir
复制代码
如果将foo目录打包成bar.har后,获取file-1的命令就变成
  1. hadoop fs –get har://namenode/bar.har#foo/file-1 localdir
复制代码
通过以下命令可以将文件打包成HAR。
hadoop archive -archiveName  *但是,目前HAR文件中的源数据只能获取,不能修改,文章中提到实现可以修改将是下一步的工作。
参考文章:


大数据中国(http://www.bigdatas.cn),以数据的力量改变生活!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

大数据中国微信

QQ   

版权所有: Discuz! © 2001-2013 大数据.

GMT+8, 2024-12-22 20:08 , Processed in 0.066211 second(s), 28 queries .

快速回复 返回顶部 返回列表