你好,游客 登录 注册 搜索
背景:
阅读新闻

Hadoop上小文件存储处理

[日期:2016-04-25] 来源:并发编程网  作者:小村长翻译 [字体: ]

  在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最近才支持追加,一个非常通用的保存无界文件(例如日志文件)的模式是写在HDFS块.

  有的文件一直比较小. 想象一个大的图像库. 每一个文件是一个不同的文件, 没有自然的方法把它们组合成一个更大的文件.

  这两者需要不同的解决方案. 对于第一个实例, 文件是有一个个记录组成, 这个问题可以通过调用 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上的文件数量并没有减少.

Hadoop

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

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

  HBase

 

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





收藏 推荐 打印 | 录入:elainebo | 阅读:
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款