【问题标题】:How to set data block size in Hadoop ? Is it advantage to change it?如何在 Hadoop 中设置数据块大小?改变它有好处吗?
【发布时间】:2016-03-28 22:55:40
【问题描述】:

如果我们可以更改 Hadoop 中的数据块大小,请告诉我该怎么做。 更改块大小是否有利,如果是,请告诉我为什么以及如何?如果不是,请告诉我原因和方法?

【问题讨论】:

标签: hadoop hdfs bigdata cloudera hortonworks-data-platform


【解决方案1】:

您可以随时更改块大小,除非在 hdfs-site.xml 中将 dfs.blocksize 参数定义为 final。

改变块大小

  1. 在运行hadoop fs 命令时,您可以运行hadoop fs -Ddfs.blocksize=67108864 -put <local_file> <hdfs_path>。此命令将保存 64MB 块大小的文件
  2. 在运行 hadoop jar 命令时 - hadoop jar <jar_file> <class> -Ddfs.blocksize=<desired_block_size> <other_args>。 Reducer 将使用定义的块大小,同时将输出存储在 HDFS 中
  3. 作为 map reduce 程序的一部分,您可以使用 job.set 并设置值

改变块大小的标准:

  1. 通常 128 MB 的未压缩文件效果很好
  2. 您可以考虑减小压缩文件的块大小。如果压缩率太高,那么具有更大的块大小可能会减慢处理速度。如果压缩编解码器不可拆分,则会加剧问题。
  3. 只要文件大小大于块大小,就不需要更改块大小。如果要处理数据的映射器数量非常多,您可以通过增加拆分大小来减少映射器的数量。例如,如果您有 1TB 的数据和 128 MB 的块大小,那么默认情况下它将占用 8000 个映射器。您可以考虑将拆分大小更改为 512 MB 甚至 1 GB,而不是更改块大小,这样处理数据所需的映射器数量就会少得多。

我已经在performance tuning 播放列表的第 2 和第 3 中介绍了大部分内容。

【讨论】:

    【解决方案2】:

    关于这个话题似乎有很多困惑,而且还有错误的建议。为了消除困惑,考虑一下 HDFS 的实际实现方式会有所帮助:

    HDFS 是基于分布式磁盘的文件系统的抽象。因此,“块”和“块大小”这两个词的含义与通常理解的不同。对于 HDFS,“文件”只是块的集合,每个“块”作为回报存储为数据节点上的实际文件。事实上,根据复制因子,同一个文件存储在多个数据节点上。这些单个文件的块大小以及它们的其他性能特征又取决于各个数据节点的底层文件系统。

    HDFS 文件和数据节点上的单个文件之间的映射得到维护 通过名称节点。但是namenode并不期望特定的块大小,它只是存储 在创建 HDFS 文件期间创建的映射,通常是拆分的 根据默认的dfs.blocksize(但可以单独覆盖)。

    这意味着,例如,如果您有 1 MB 的文件,副本为 3,块大小为 64 MB,您不会丢失 63 MB * 3 = 189 MB,因为实际上只存储了三个 1 MB 的文件 使用底层文件系统的标准块大小(例如 ext4)。

    所以问题变成了dfs.blocksize 是什么好,以及是否建议更改它。 让我首先列出代表更大块大小的方面:

    1. Namenode 压力:如前所述,namenode 必须维护 dfs 文件及其块与数据节点上的物理文件之间的映射。因此,块/文件越少,内存压力和通信开销就越小
    2. 磁盘吞吐量:文件由hadoop中的单个进程写入,这通常会导致数据顺序写入磁盘。这对于旋转磁盘特别有利,因为它避免了昂贵的寻道。如果数据以这种方式写入,它也可以以这种方式读取,因此它成为读取和写入的优势。事实上,这种结合本地数据的优化(即在数据所在的地方进行处理)是 mapreduce 的主要思想之一。
    3. 网络吞吐量:数据局部性是更重要的优化,但在分布式系统中,这并不总是能够实现,因此有时需要在节点之间复制数据。通常一个文件(dfs 块)通过一个持久的 TCP 连接传输,当传输大文件时可以达到更高的吞吐量。
    4. 更大的默认拆分:即使可以在作业级别配置拆分大小,但大多数人不会考虑这一点,而只是使用默认值,通常是块大小。但是,如果您的 splitsize 太小,您最终可能会得到太多没有太多工作要做的映射器,这反过来又会导致输出文件更小、不必要的开销和许多占用的容器,这可能会导致其他工作饿死。这对 reduce 阶段也有不利影响,因为必须从所有映射器中获取结果。

      当然,理想的分割尺寸在很大程度上取决于您要做的工作类型。但是你总是可以在必要时设置一个较低的 splitsize,而当你设置一个比 blocksize 更高的 splitsize 时,你可能会丢失一些数据局部性。

      后一个方面的问题比人们想象的要小,因为 HDFS 中块放置的规则是:第一个块写入创建文件的进程运行的数据节点上,第二个块写入另一个节点同一个机架和第三个机架在另一个机架上的节点上。因此,通常可以在单个数据节点上找到文件的每个块的一个副本,因此即使一个映射器由于分割大小是块大小的倍数而读取多个块,仍然可以实现数据局部性。仍然在这种情况下,mapred框架只能选择一个节点而不是通常的三个节点来实现数据局部性,因此不能否认效果。

      但最终,对于更大的块大小,这一点可能是最弱的,因为如果需要,可以独立设置拆分大小。

    但是对于更小的块大小也必须有参数,否则我们应该将其设置为无穷大……

    1. 并行/分布:如果您的输入数据仅位于几个节点上,那么即使是一个大集群也无助于实现并行处理,至少如果您想保持一些数据局部性。作为一项规则,我会说一个好的块大小应该与您也可以接受的默认工作负载的拆分大小相匹配。
    2. 容错和延迟:如果网络连接中断,重新传输较小文件的干扰就会减少。 TCP 吞吐量可能很重要,但单个连接也不应该永远持续下去。

    将这些因素相互加权取决于您的数据类型、集群、工作负载等。但总的来说,我认为默认的块大小 128 MB 对于典型的用例来说已经有点低了。 512 MB 甚至 1 GB 可能值得考虑。

    但在深入研究之前,您应该首先检查输入文件的大小。如果您的大多数文件都很小并且甚至没有达到最大默认块大小,那么您的块大小基本上总是文件大小,并且增加默认块大小无济于事。有一些解决方法,例如使用输入组合器来避免生成过多的映射器,但最终您需要确保输入文件足够大以利用大块大小。

    如果您的文件已经很小,请不要通过使块大小更小来加剧问题。

    【讨论】:

    • 我有一个关于磁盘吞吐量和网络吞吐量的查询
    • 第一个关于磁盘吞吐量的问题。您曾提到数据将按顺序写入磁盘。因此,如果我在从节点中有 64 mb 的数据,则将在从节点的磁盘中顺序形成 8kb 的 64 mb 数据块,以减少寻道时间。当数据被写入或读取时,它会在 8kb 块中处理吗?对吗?
    • “过程”是什么意思?在硬件层面?内核级别?应用层?为什么这对你很重要?你想解决什么样的问题?
    • 数据将驻留在具有 4 kb 块的数据节点的硬盘中。我只是想知道这些数据是如何读取的?
    • 我对 8kb 和 128mb 块大小感到困惑。数据以 8kb 块驻留在硬盘中,以 8kb 块读取,那么为什么要划分为 128mb?
    【解决方案3】:

    这取决于输入数据。映射器的数量与输入拆分成正比,这取决于 DFS 块大小。

    如果您想最大化超大输入文件的吞吐量,最好使用超大块(128MB 甚至 256MB)。

    如果作业的输入量超过 1TB,可以考虑将输入数据集的块大小增加到 256M 甚至 512M,这样任务的数量就会更少。

    对于较小的文件,使用较小的块大小更好。

    看看这个article

    如果您有小文件并且小于最小 DFS 块大小,您可以使用一些替代方案,例如 HAR 或 SequenceFiles。

    看看这个cloudera博客

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 2016-05-30
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多