Hadoop 大量小文件和128 Mb块大小上的HDFS行为

Hadoop 大量小文件和128 Mb块大小上的HDFS行为,hadoop,hdfs,Hadoop,Hdfs,我有很多(多达几十万)小文件,每个10-100KB。我的HDFS块大小等于128 MB。我的复制因子等于1 为每个小文件分配HDFS块有什么缺点吗? 我看到了非常矛盾的答案: 我做了一个类似于中的测试,它证明了第二个选项是正确的——HDFS不会将整个块分配给小文件 但是,从HDFS批量读取10000个小文件怎么样?它是否会因为10000个块和元数据而变慢?是否有理由将多个小文件保存在单个块中? 更新:我的用例 我只有一个小文件用例,从1.000到500.000。我计算这些文件一次,存储它,然

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

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

我看到了非常矛盾的答案:

  • 我做了一个类似于中的测试,它证明了第二个选项是正确的——HDFS不会将整个块分配给小文件

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

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

    1) 据我所知,NameNode空间问题对我来说不是问题。500.000是绝对上限,我再也不会有更多了。如果NN上的每个小文件占用150字节,则me的绝对最大值为-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);
    

    正如您已经注意到的,HDFS文件占用的空间不会超过它所需的空间,但是在HDFS集群中包含小文件还有其他缺点。让我们先看看问题,不考虑配料:

  • 名称节点(NN)内存消耗。我不知道Hadoop 3(目前正在开发中),但在以前的版本中,NN是一个单点故障(您可以添加辅助NN,但它最终不会替换或增强主NN)。NN负责维护内存和磁盘上的文件系统结构,资源有限。NN维护的文件系统对象中的每个条目被认为是150字节()。更多文件=NN消耗的RAM更多
  • MapReduce范例(据我所知,Spark也有同样的症状)。在Hadoop中,映射器是按分割分配的(默认情况下对应于块),这意味着,对于存在的每个小文件,都需要启动一个新的映射器来处理其内容。问题是,对于小文件,Hadoop启动映射程序所需的时间实际上要比处理文件内容所需的时间多得多。基本上,您的系统将执行启动/停止映射程序的不必要工作,而不是实际处理数据。这就是Hadoop处理128MB文件(块大小为128MB)比处理1281MB文件(块大小相同)快得多的原因
  • 现在,如果我们谈论批处理,您可以选择的选项很少:HAR、序列文件、Avro模式等等。这取决于用例对您的问题给出准确的答案。假设您不想合并文件,在这种情况下,您可能正在使用HAR文件(或任何其他具有高效归档和索引功能的解决方案)。在这种情况下,NN问题得到解决,但映射器的数量仍将等于拆分的数量。如果可以选择将文件合并为大文件,您可以使用序列文件,它基本上将小文件聚合为大文件,在一定程度上解决了这两个问题。在这两种情况下,虽然您不能像处理小文件那样直接更新/删除信息,但是需要更复杂的机制来管理这些结构


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

    请指定批读取(序列文件?HAR?任何其他聚合?)的含义。在您提供第一个问题的更多详细信息后,我将回答您的其余问题。@Serhiy假设我有10k个小文件,需要立即将它们全部读入内存。谢谢您的完整回答!我非常感激。你能看一下我问题的更新部分吗?我建议你提出另一个问题,因为我不是火花专家,这个问题太广泛了。只是一种推测,据我所知,小文件也是Spark的一个问题,除非您编写自定义加载程序或序列文件/其他文件聚合格式可以减少文件加载时间(再一次,这只是猜测,再一次,我不是Spark专家)。“对于每个小文件…一个新的映射器”>这是默认值,但是Hadoop
    CombineFileInputFormat
    已经被专门创建来缓冲每个映射器的多个小拆分;在配置单元中通过
    Hive.hadoop.supports.splittable.combineinputformat
    属性使用:“是否合并小的输入文件以便生成更少的映射程序”--另请参见中的
    Hive.input.format