Hadoop上小文件存储处理

原文链接   译者:小村长

Hadoop–小文件存储处理

本篇文章项目是Cloudera论坛中无意中看到的,虽然原文写于2009年,但是当前开来Hadoop的小文件存储方案并没有很好的解决方案,所以感觉作者写的很好,也很详细,于是就抽空翻译了。本次翻译主要针对对Hadoop感兴趣和工作中使用到Hadoop的开发人员提供有价值的中文资料,希望能够对大家的工作和学习有所帮助。

由于我英语水平有限,部分翻译虽能了解其大意,但是却没法很好的表达出来,所以有些地方翻译的不是很好。同时也由于能力见识有限,翻译过程中难免出现个人的主观或者客观原因导致与原文档有差异。在此,我还是建议有能力的童鞋能够自己去原文看看,同时如果大家发现更好的关于Hadoop小文件处理的文件,也建议大家提出来与大家一同分享。

 

小文件问题

Categories: General Hadoop

在Hadoop中小文件是一个大问题 — 或者说, 至少, 他们在用户的讨论区域是比较热门的话题. 在这篇文章中我将直面这个问题, 并提出一些常见的解决方案.

在HDFS中的小文件问题

这里讨论的小文件指的是那些在HDFS中小于HDFS块大小(默认是64M)的文件. 如果你存储了很多这种小文件, 或者你有很多这种小文件 (如果你并没有使用Hadoop), 这里讨论的问题是Hadoop不能处理大量的这种文件.

每一个文件, 目录和块在HDFS中代表一个对象存储在namenode的内存中, 它们每一个占用150 字节, 根据经验. 所以1000万个文件,每一个使用一个块, 将大约需要3GB的内存. 远远超过当前的硬件处理水平. 当然10亿个文件直接没法处理.

此外, HDFS是没有能力去有效地访问小文件:它主要是专为串行流式访问的大文件设计的. 阅读小文件通常会导致从一个DataNode到DataNode检索每个小文件, 所有的这些访问数据效率都是很低下的.

在MapReduce中小文件问题

Map任务每次能处理一个块的输入 (使用的是默认的 FileInputFormat). 如果文件非常小而且还很多, 导致每次Map任务产生非常小的输入, 同时这里需要大量的map任务, 这样增加了很多额外的开销. 比较一个1GB 文件分成16 64MB 块, 10,000 或者 100KB 文件. 10,000文件每个文件使用一个map任务, 这个任务比一个相等的大文件要慢10或者上百倍.

这里有一些特征能够减轻额外的开销:多个任务使用一个JVM, 从而避免了一些JVM启动开销 (看mapred.job.reuse.jvm.num.tasks 属性), 和MultiFileInputSplit 可以运行多个以上的分割任务.

小文件怎么产生的?

这里至少有两个场景

这两者需要不同的解决方案. 对于第一个实例, 文件是有一个个记录组成, 这个问题可以通过调用 HDFS’s sync() 方法来避免 (这个是追加, 深入了解可以看 this discussion) 每一个如此频繁地写大文件. 另外,你可以通过写一个程序来把小文件连接在一起 (查看 Nathan Marz’s post 工具能够实现这种功能).

对于第二种情况,通过一些方式来对文件进行分组操作. Hadoop提供了几种方案.

HAR files

Hadoop Archives (HAR 文件)被引入到HDFS在0.18.0版本中为了减轻存放许多文件在namenode内存中的问题. HAR 文件的工作原理是在HDFS中建立一个分层的文件系统. 一个 HAR文件创建通过使用hadoop archive 命令,他通过运行一个MapReduce任务把HDFS中的小文件进行打包. 对于客户端使用HAR文件系统没有改变: 所有的原始文件是可见的和可访问的 (通过使用 har:// URL). 然而, 在HDFS上的文件数量并没有减少.
SequenceFile and MapFile File Layouts

在HDFS上读文件比HAR上面效率要高一些, 事实上,可能会比较慢因为每个HAR文件访问需要两个索引文件的读取以及数据文件的读取(见下图). 虽然HAR文件能够作为MapReduce的输入文件 , HAR并没有准许在进行Map操作的时候把所有的文件当着一个块来操作. 它应该是提供一个输入的格式能够在HARs提升改进的地方, 实际上它并没有. 请注意 MultiFileInputSplit, 即使在 HADOOP-4565 通过选择本地文件分割来提高, 将也需要查询每一个小的文件. 通过与SequenceFile文件性能比较是很有趣的, 所以说.现在HARs最常使用的是来处理文档.

Sequence Files

通常回答关于“小文件问题” 是: 使用SequenceFile. SequenceFile文件的设计思想是使用文件名作为key文件内容作为值. 这在实践中很好. 回到10,000 100KB 文件问题, 你可以写一个程序把他们放到一个单独的SequenceFile文件里面, 并且你可以通过串流的形势对其进行访问(直接或者通过MapReduce) 在SequenceFile文件上进行操作. 更神奇的地方是. SequenceFiles文件能够被可拆分, 所以MapReduce可以打破成块,每一块独立操作. 它们也支持压缩, 不像HARs. 块压缩是大多数情况下最好的选择, 由于压缩了几个记录块(相当于每个记录).

它可以将现有的数据转化成为SequenceFiles. 然而,完全有可能在并行创建一系列sequencefiles. (Stuart Sierra 已经写了一篇很有用的关于 post 转换tar文件到SequenceFile文件 — 这种工具是很有益的, 看到更多的人会很好).最好的设计在写入数据的时候直接写入到SequenceFiles文件里面, 如果可能,而不是写小文件作为中间步骤.

HAR File Layout
不像HAR文件, SequenceFile文件没法罗列出所有的keys,简短的阅读需要获取通过整个文件. (MapFiles文件很像一个已经对key进行排序的 SequenceFiles 文件, 维护部分索引, 所以他们不能罗列所有它们的keys — 如图所示.)

SequenceFile文件相当于Java的核心. TFile文件被设计成跨平台的, 是一个可以替代的 SequenceFile, 但它尚未提供.

HBase

如果你产生了很多小文件, 然而, 根据访问模式, 不同类型的存储可能更合适. HBase 存储数据通过MapFiles (索引SequenceFiles), 是一个很好的选择如果你需要MapReduce流分析同时也需要随机访问查看. 如果延迟是一个问题, 然而这里有许多其他的选择 — 看Richard Jones’ 杰出的survey of key-value stores.

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/117110.html

(0)
上一篇 2021年8月28日
下一篇 2021年8月28日

相关推荐

发表回复

登录后才能评论