hdfs-加载大量文件

2lpgd968  于 2021-06-02  发布在  Hadoop
关注(0)|答案(5)|浏览(804)

出于测试目的,我尝试将大量的小文件加载到hdfs中。实际上,我们讨论的是100万(100万)个文件,大小从1kb到100kb。我在linux系统的一个文件夹中用r脚本生成了这些文件。每个文件都有一个信息结构,其中包含一个包含产品信息的标题和不同数量的包含数字信息的列。
问题是,当我尝试使用以下命令将这些本地文件上载到hdfs时:

hdfs dfs -copyFromLocal /home/user/Documents/smallData /

然后出现以下java堆大小错误之一:
线程“main”java.lang.outofmemoryerror中出现异常:java堆空间
线程“main”java.lang.outofmemoryerror中出现异常:超出gc开销限制
我使用clouderacdh5发行版,java堆大小约为5gb。有没有其他方法比增加java堆的大小更有效?也许是一个更好的方法来加载大量的数据到hdfs中?
我非常感谢每一个有用的评论!

iovurdzv

iovurdzv1#

hadoop分布式文件系统不适合处理许多小文件,但适合处理许多大文件。hdfs在一个查找表中保存一条记录,该表指向hdfs中的每个文件/块,这个查找表通常加载到内存中。因此,不仅要增加java堆大小,还要增加hadoop-env.sh中name节点的堆大小,这是默认值:

export HADOOP_HEAPSIZE=1000
export HADOOP_NAMENODE_INIT_HEAPSIZE="1000"

如果要对这些文件进行处理,则在运行它们的第一个mapreduce作业时,应该期望性能较低(hadoop创建的map任务数等于文件/块数,这将使系统过载,除非使用combineinputformat)。建议您将文件合并为大文件(64mb/128mb)或使用其他数据源(而不是hdfs)。

nvbavucw

nvbavucw2#

为了解决这个问题,我构建了一个具有某种格式的文件。文件的内容都是小文件。格式如下:

<DOC>
  <DOCID>1</DOCID>
  <DOCNAME>Filename</DOCNAME>
  <DOCCONTENT>
    Content of file 1
  </DOCCONTENT>
</DOC>

这种结构可以是或多或少的领域,但想法是一样的。例如,我使用了以下结构:

<DOC>
  <DOCID>1</DOCID>
  Content of file 1
</DOC>

处理超过六百万个文件。
如果希望为一个Map任务处理每个文件,则可以在和标记之间删除\n char。在这之后,您只需要解析结构并拥有文档标识符和内容。

eivgtgni

eivgtgni3#

首先:如果这不是对namenode的压力测试,那么这样做是不明智的。但我想你知道你在做什么(预计进展缓慢)
如果目标只是在hdfs上获取文件,那么可以尝试在较小的批处理中进行,或者在hadoop客户机上设置更高的堆大小。
你这样做就像他在回答中提到的rpc1一样 HADOOP_HEAPSIZE=<mem in Mb here> 给你的 hadoop -put 命令。

zf2sa74q

zf2sa74q4#

试着增加治愈率

HADOOP_HEAPSIZE=2048 hdfs dfs -copyFromLocal /home/user/Documents/smallData

看这里

uoifb46i

uoifb46i5#

如果要增加内存并将文件存储在hdfs中。在这之后,在处理的时候你会遇到很多问题。

Problems with small files and HDFS

小文件是一个明显小于hdfs块大小(默认64mb)的文件。如果您存储的是小文件,那么您可能有很多文件(否则就不会使用hadoop),问题是hdfs不能处理很多文件。
hdfs中的每个文件、目录和块都表示为namenode内存中的一个对象,根据经验,每个对象占用150字节。所以1000万个文件,每个文件使用一个块,将使用大约3g的内存。扩展到这个级别之外是当前硬件的一个问题。当然,十亿个文件是不可行的。
此外,hdfs还不能有效地访问小文件:它主要是为大文件的流式访问而设计的。读取小文件通常会导致大量的查找和从datanode到datanode的大量跳跃来检索每个小文件,所有这些都是一种低效的数据访问模式。

Problems with small files and MapReduce

Map任务通常一次处理一个输入块(使用默认的fileinputformat)。如果文件非常小并且有很多,那么每个map任务处理的输入非常少,并且有更多的map任务,每个map任务都会带来额外的簿记开销。将一个1gb的文件分成16个64mb的块,与10000个左右100kb的文件进行比较。10000个文件每个使用一个Map,作业时间可能比使用单个输入文件的等效文件慢几十倍或几百倍。
有两个特性可以帮助减轻簿记开销:任务jvm重用用于在一个jvm中运行多个map任务,从而避免一些jvm启动开销(请参阅mapred.job.reuse.jvm.num.tasks属性),以及multifileinputsplit,它可以在每个map中运行多个split。

SOLUTION

创建 .HAR 文件hadoop归档(har文件)在0.18.0中引入到hdfs中,以减轻大量文件对namenode内存的压力。har文件通过在hdfs之上构建一个分层文件系统来工作。har文件是使用hadoop archive命令创建的,该命令运行mapreduce作业,将要归档的文件打包到少量hdfs文件中

hadoop archive -archiveName name -p <parent> <src>* <dest> 
hadoop archive -archiveName foo.har -p /user/hadoop dir1 dir2 /user/zoo

下一个是

Sequence Files

对于“小文件问题”的回答通常是:使用sequencefile。这里的想法是使用文件名作为键,文件内容作为值。这在实践中效果很好。回到10000个100kb文件,您可以编写一个程序将它们放入一个sequencefile中,然后您可以以流式方式(直接或使用mapreduce)对sequencefile进行处理。还有一些奖金。SequenceFile是可拆分的,因此mapreduce可以将它们拆分为块,并独立地对每个块进行操作。它们也支持压缩,不像hars。块压缩在大多数情况下是最好的选择,因为它压缩多个记录的块(而不是每个记录)

HBase

如果要生成大量的小文件,则根据访问模式,可能更适合使用不同类型的存储。hbase将数据存储在mapfiles(索引的sequencefiles)中,如果您需要偶尔随机查找mapreduce样式的流分析,它是一个很好的选择。如果延迟是一个问题,那么还有很多其他的选择

相关问题