【问题标题】:HDFS behavior on lots of small files and 128 Mb block size大量小文件和 128 Mb 块大小的 HDFS 行为
【发布时间】:2017-05-08 14:06:48
【问题描述】:

我有很多(多达数十万个)小文件,每个 10-100 Kb。我的 HDFS 块大小等于 128 MB。我的复制因子等于 1。

为每个小文件分配 HDFS 块有什么缺点吗?

我看到了相当矛盾的答案:

  1. Answer which said the smallest file takes the whole block
  2. Answer which said that HDFS is clever enough, and small file will take small_file_size + 300 bytes of metadata

我做了一个类似this answer 的测试,它证明了第二个选项是正确的——HDFS 不会为小文件分配整个块。

但是,从 HDFS 批量读取 10.000 个小文件怎么样?它会因为 10.000 个块和元数据而变慢吗?是否有任何理由将多个小文件保存在一个块中?

更新:我的用例

我只有一个小文件用例,从 1.000 到 500.000。我计算这些文件一次,存储它,然后一次读取它们。

1) 据我了解,NameNode 空间问题对我来说不是问题。 500.000 是绝对最大值,我永远不会有更多。如果每个小文件在 NN 上占用 150 字节,那么我的绝对最大值是 - 71.52 MB,这是可以接受的。

2) Apache Spark 是否消除了 MapReduce 问题?序列文件或 HAR 会帮助我解决问题吗? 据我了解,Spark 不应该依赖 Hadoop MR,但它仍然太慢。读取 490 个文件需要 38 秒,读取 3420 个文件 - 266 秒。

sparkSession
    .read()
    .parquet(pathsToSmallFilesCollection)
    .as(Encoders.kryo(SmallFileWrapper.class))
    .coalesce(numPartitions);

【问题讨论】:

  • 请说明批量读取的含义(序列文件?HAR?任何其他聚合?)。在您提供有关第一个问题的更多详细信息后,我将回答您的其余问题。
  • @Serhiy 假设我有 10k 个小文件,需要一次将它们全部读入内存。

标签: hadoop hdfs


【解决方案1】:

正如您已经注意到的那样,HDFS 文件占用的空间不会超过它所需的空间,但是在 HDFS 集群中拥有小文件还有其他缺点。让我们先解决问题,不考虑批处理:

  1. NameNode(NN) 内存消耗。我不知道 Hadoop 3(目前正在开发中),但在以前的版本中,NN 是单点故障(您可以添加辅助 NN,但它不会在最后替换或增强主 NN)。 NN 负责维护内存和磁盘上的文件系统结构,资源有限。 NN 维护的文件系统对象中的每个条目被认为是 150 字节 (check this blog post)。更多文件 = NN 消耗更多 RAM。
  2. MapReduce 范例(据我所知,Spark 也有同样的症状)。在 Hadoop Mapper 中,每个拆分都被分配(默认情况下对应于块),这意味着对于您拥有的每个小文件,都需要启动一个新的 Mapper 来处理其内容。问题是对于小文件,Hadoop 启动 Mapper 比处理文件内容实际上需要更多的时间。基本上,您的系统将执行启动/停止 Mappers 的不必要工作,而不是实际处理数据。这就是 Hadoop 处理 1 128MBytes 文件(具有 128MBytes 块大小)而不是 128 个 1MBytes 文件(具有相同块大小)的原因。

现在,如果我们谈论批处理,您可以选择的选项很少:HAR、序列文件、Avro 模式等。这取决于用例来为您的问题提供准确的答案。假设您不想合并文件,在这种情况下,您可能正在使用 HAR 文件(或任何其他具有高效归档和索引功能的解决方案)。在这种情况下,NN 问题得到了解决,但 Mapper 的数量仍将等于拆分的数量。如果可以选择将文件合并为大文件,您可以使用序列文件,它基本上将小文件聚合成更大的文件,从而在一定程度上解决了这两个问题。在这两种情况下,虽然您无法像处理小文件那样直接更新/删除信息,因此需要更复杂的机制来管理这些结构。

一般来说,维护许多小文件的主要原因是为了进行快速读取,我建议看看 HBase 等不同的系统,这些系统是为快速数据访问而不是批处理而创建的。

【讨论】:

  • 感谢您提供如此完整的回答!我很感激。你能看看我的问题的更新部分吗?
  • 我建议您再提出一个问题,因为我不是 Spark 专家,而且这个问题太宽泛了。只是一个猜测,据我所知,小文件也是 Spark 的一个问题,除非您编写自定义加载器或 也许 序列文件/其他文件聚合格式可以减少文件加载时间(再次此只是猜测,我再次不是 Spark专家)。
  • "对于每个小文件...一个新的 Mapper" > 这是默认设置,但 Hadoop CombineFileInputFormat 专门用于缓冲每个 Mapper 的多个小拆分;通过 hive.hadoop.supports.splittable.combineinputformat 属性在 Hive 中使用:“是否合并小型输入文件以便生成更少的映射器” -- 另请参阅 hive.input.format in cwiki.apache.org/confluence/display/Hive/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2020-07-29
  • 1970-01-01
  • 1970-01-01
  • 2018-12-26
  • 1970-01-01
  • 2020-02-24
相关资源
最近更新 更多