HDFS存储大量小文件的问题及解决方案

HDFS存储大量小文件的问题及解决方案,第1张

HDFS存储大量小文件的问题及解决方案 1.存储大量小文件存在的问题
  1. 大量小文件的存在势必占用大量的 NameNode 内存
    HDFS 中的每一个文件、目录以及文件块,在 NameNode 内存都会有记录,每一条记录大约占用150字节的内存空间(该大小与文件、目录及文件块的大小无关),namenode的内存就会成为HDFS 的横向扩展能力的一个限制因素。

  2. 如果我们使用 MapReduce 任务来处理这些小文件,因为每个 Map 会处理一个 HDFS 块;这会导致程序启动大量的 Map 来处理这些小文件,( 读取小文件数据的任务执行时,消耗过多的集群资源。因为map task在执行的时候一般只处理1个文件,如果这个时候要读取的文件过多,就会造成大量的map task启动。) 虽然这些小文件总的大小并非很大,却占用了集群的大量资源!

2.大量小文件产生的情况
  • **实时流处理:**比如我们使用 Spark Streaming 从外部数据源接收数据,然后经过 ETL 处理之后存储到 HDFS 中。这种情况下在每个 Job 中会产生大量的小文件。
  • **MapReduce 产生:**我们使用 Hive 查询一张含有海量数据的表,然后存储在另外一张表中,而这个查询只有简单的过滤条件(比如 select * from iteblog where from = ‘hadoop’),这种情况只会启动大量的 Map 来处理,这种情况可能会产生大量的小文件。也可能 Reduce 设置不合理,产生大量的小文件。
  • **数据本身的特点:**比如我们在 HDFS 上存储大量的图片、短视频、短音频等文件,由于这些文件的特点,而且数量众多,也可能给 HDFS 大量灾难。
Hadoop提供的解决方案

分别为:Hadoop Archive,Sequence file和CombineFileInputFormat。

(1)Hadoop Archive

Hadoop Archive或者HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问。

从上图我们可以看出,Hadoop在归档文件时通过二层索引文件的查找,进行最终文件的读取。所以在效率上会比普通HDFS读取文件慢一些。

对某个目录/foo/bar下的所有小文件存档成/outputdir/ zoo.har:

hadoop archive -archiveName zoo.har -p /foo/bar /outputdir

当然,也可以指定HAR的大小(使用-Dhar.block.size)。

HAR是在Hadoop file system之上的一个文件系统,因此所有fs shell命令对HAR文件均可用,只不过是文件路径格式不一样,HAR的访问路径可以是以下两种格式:

har://scheme-hostname:port/archivepath/fileinarchive

har:///archivepath/fileinarchive(本节点)

可以这样查看HAR文件存档中的文件:

hadoop dfs -ls har:///user/zoo/foo.har

输出:

har:///user/zoo/foo.har/hadoop/dir1

har:///user/zoo/foo.har/hadoop/dir2

创建存档文件的问题:
1、存档文件的源文件目录以及源文件都不会自动删除需要手动删除
2、存档的过程实际是一个mapreduce过程,所以需要需要hadoop的mapreduce的支持
3、存档文件本身不支持压缩
4、存档文件一旦创建便不可修改,要想从中删除或者增加文件,必须重新建立存档文件
5、创建存档文件会创建原始文件的副本,所以至少需要有与存档文件容量相同的磁盘空间
6、要归档的文件名中不能有空格,否则会抛出异常,可以将空格用其他符号替换(使用-Dhar.space.replacement.enable=true 和-Dhar.space.replacement参数)。
7、对于一个mapreduce任务来说,如果使用HAR文件作为其输入,仍旧是其中每个小文件对应一个map task,效率低下。所以,HAR files最好是用于文件归档。

(2)Sequence File

sequence file由一系列的二进制key/value组成,其中key为小文件名,value为文件内容,则可以将大批小文件合并成一个大文件,通过改变文件的写出方式,写入到SequenceFile格式的文件中。这主要是因为SequenceFile独有的存储格式决定了它可以很好的满足小文件存储的需求。SequenceFile文件内部存储数据的方式是以下面key-value的形式拼接而成。

因为考虑到小文件中的内容少,在这里我们可以以文件名作为key,文件内容作为value,直接写到SequenceFile中。
通常对于"小文件问题"的回应会是:使用序列文件(SequenceFile)。这种方法的思路是,使用文件名(filename)作为key,并且文件内容(file contents)作为value。
将大量小文件放入一个单一的SequenceFile,流式处理 *** 作SequenceFile的两个优势:

  1. SequenceFiles是可拆分的,因此MapReduce可以将它们分成块并独立地对每个块进行 *** 作;
  2. 它们同时支持压缩,不像HAR。 在大多数情况下,块压缩是最好的选择,因为它将压缩几个记录为一个块,而不是一个记录压缩一个块。
(3)CombineFileInputFormat

CombineFileInputFormat是一种新的inputformat,用于将多个文件合并成一个单独的split。功能,是将一个目录(可能包括多个小文件,不包括子目录)作为一个map的输入,而不是通常使用一个文件作为输入。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5696503.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存