如何在Hadoop中设置数据块大小?改变它有利吗?

时间:2015-12-22 16:04:51

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

如果我们可以在Hadoop中更改数据块大小,请告诉我如何操作。 更改块大小是否有利,如果是,那么让我知道为什么以及如何?如果没有,那么让我知道为什么以及如何?

3 个答案:

答案 0 :(得分:2)

这个话题似乎有很多混乱,也有错误的建议。为了解除混乱,有必要考虑HDFS的实际实施方式:

HDFS是基于分布式磁盘的文件系统的抽象。所以"阻止"和" blocksize"具有与通常理解的不同的含义。对于HDFS a"文件"只是一个块的集合,每个块"块"作为回报,将其存储为datanode上的实际文件。事实上,根据复制因素,同一文件存储在多个数据节点上。这些单个文件的块大小及其他性能特征依赖于各个数据节点的底层文件系统。

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

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

所以问题变成了一个好的dfs.blocksize,以及是否可以改变它。 让我首先列出更大块大小的方面:

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

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

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

    但最终这个更大的块大小的点可能是最弱的,因为必要时可以独立设置splitsize。

  5. 但是对于较小的块大小也必须有参数,否则我们应该将它设置为无穷大......

    1. 并行/分布:如果您的输入数据仅位于几个节点上,即使大型集群也无法帮助实现并行处理,至少如果您想维护某些数据位置。作为一项规则,我会说一个好的块大小应该与你可以接受的默认工作负载的splitsize相匹配。
    2. 容错和延迟:如果网络连接中断了重传较小文件的扰动较少。 TCP吞吐量可能很重要,但个别连接也不应该永远。
    3. 将这些因素相互加权取决于您的数据类型,群集,工作负载等。但总的来说,我认为默认的块大小128 MB对于典型的用例来说已经有点低了。 512 MB甚至1 GB可能值得考虑。

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

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

答案 1 :(得分:1)

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

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

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

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

看看这个article

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

查看此cloudera博客

答案 2 :(得分: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并设置值
  4. 更改块大小的标准:

    1. 通常,128 MB的未压缩文件效果很好
    2. 您可以考虑减少压缩文件的块大小。如果压缩率太高,则具有更高的块大小可能会减慢处理速度。如果压缩编解码器不可拆分,则会加剧问题。
    3. 只要文件大小超过块大小,就不需要更改块大小。如果处理数据的映射器数量非常多,则可以通过增加分割大小来减少映射器的数量。例如,如果您有1TB的数据块大小为128 MB,那么默认情况下它将需要8000个映射器。您可以考虑将分割大小更改为512 MB甚至1 GB,而不是更改块大小,并且处理数据的映射器数量将会少得多。
    4. 我已经在这个performance tuning播放列表中的2和3中涵盖了大部分内容。