hadoop-大小不同(200-500mb)的不可散播文件的适当块大小

rslzwgfq  于 2021-06-04  发布在  Hadoop
关注(0)|答案(2)|浏览(346)

如果我需要对大小在200到500mb之间的数千个gzip文件(不可拆分)进行顺序扫描,那么这些文件的合适块大小是多少?
为了解决这个问题,假设处理速度非常快,因此重新启动Map器并不昂贵,即使对于大的块大小也是如此。
我的理解是:
几乎没有一个块大小的上限,因为有“大量的文件”为适当数量的Map器为我的集群的大小。
为了确保数据的局部性,我希望每个gzip文件位于1个块中。
但是,gzip文件的大小不同。如果我选择块大小为~500mb(例如,所有输入文件的最大文件大小),数据是如何存储的?最好选择一个“非常大”的块大小,比如2gb?在这两种情况下,硬盘容量是否过度浪费?
我想我真的是在问文件是如何在hdfs块之间存储和分割的,同时也在试图了解不可分割文件的最佳实践。
更新:一个具体的例子
假设我在三个200MB的文件上运行mr作业,存储如下图所示。
如果hdfs像案例a那样存储文件,那么3个Map器将保证每个Map器能够处理一个“本地”文件。但是,如果文件像案例b那样存储,那么一个Map器需要从另一个数据节点获取文件2的一部分。
考虑到有大量的空闲块,hdfs是否像案例a或案例b那样存储文件?

sxpgvts3

sxpgvts31#

我将尝试通过示例来突出显示块分割与文件大小之间的差异。在hdfs中,您有:

Splittable FileA size 1GB
dfs.block.size=67108864(~64MB)

针对此文件Map的作业:

16 splits and in turn 16 mappers.

让我们看看压缩(不可拆分)文件的这种情况:

Non-Splittable FileA.gzip size 1GB
dfs.block.size=67108864(~64MB)

针对此文件Map的作业:

16 Blocks will converge on 1 mapper.

最好主动避免这种情况,因为这意味着tasktracker必须获取16个数据块,其中大部分数据块不是tasktracker的本地数据块。
最后,block、split和file的关系总结如下:

block boundary
|BLOCK           |    BLOCK       |   BLOCK        |   BLOCK ||||||||
|FILE------------|----------------|----------------|---------|
|SPLIT            |                |                |        |

拆分可以扩展到块之外,因为拆分取决于inputformat类定义,该类定义说明如何拆分可能与块大小不一致的文件,因此拆分可以扩展到块之外,以包括源中的查找点。

zengzsys

zengzsys2#

如果您有不可拆分的文件,那么最好使用更大的块大小-与文件本身一样大(或者更大,没有区别)。
如果块大小小于整个文件大小,则可能所有块都不在同一数据节点上,从而丢失数据局部性。这对于可拆分文件不是问题,因为将为每个块创建Map任务。
至于块大小的上限,我知道对于某些旧版本的hadoop,这个限制是2gb(超过这个限制块内容是不可获得的)-请参阅https://issues.apache.org/jira/browse/hdfs-96
存储块大小较大的较小文件没有坏处—要强调这一点,请考虑块大小为2 gb的1mb和2 gb文件:
1 mb—1个块,名称节点中的单个条目,每个数据节点副本上物理存储1 mb
2 gb-1块,名称节点中的单个条目,每个数据节点副本上物理存储2 gb
因此除了所需的物理存储之外,name node块表没有任何缺点(两个文件在块表中都有一个条目)。
唯一可能的缺点是复制较小的块与较大的块所需的时间不同,但另一方面,如果数据节点从集群中丢失,则分配2000 x 1 mb块进行复制的任务比单个块2 gb块慢。
更新-工作示例
鉴于这引起了一些混乱,以下是一些成功的例子:
假设我们有一个300mbhdfs块大小的系统,为了使事情更简单,我们有一个只有一个数据节点的psuedo集群。
如果要存储1100 mb的文件,那么hdfs将把该文件分解为最多300 mb的块,并以特殊的块索引文件的形式存储在数据节点上。如果要转到数据节点并查看它在物理磁盘上存储索引块文件的位置,您可能会看到如下内容:

/local/path/to/datanode/storage/0/blk_000000000000001  300 MB
/local/path/to/datanode/storage/0/blk_000000000000002  300 MB
/local/path/to/datanode/storage/0/blk_000000000000003  300 MB
/local/path/to/datanode/storage/0/blk_000000000000004  200 MB

请注意,文件不能完全被300MB整除,因此文件的最后一个块的大小是文件的模与块大小的乘积。
现在,如果我们对小于块大小的文件重复相同的练习,比如说1 mb,然后看看它将如何存储在数据节点上:

/local/path/to/datanode/storage/0/blk_000000000000005  1 MB

再次注意,数据节点上存储的实际文件是1MB,而不是一个200MB的零填充文件(我认为这是产生混淆的原因)。
现在,块大小在效率中起作用的是名称节点。对于以上两个示例,name节点需要维护文件名、块名和数据节点位置(以及总文件大小和块大小)的Map:

filename     index     datanode
-------------------------------------------
fileA.txt    blk_01    datanode1
fileA.txt    blk_02    datanode1
fileA.txt    blk_03    datanode1
fileA.txt    blk_04    datanode1
-------------------------------------------
fileB.txt    blk_05    datanode1

您可以看到,如果要对filea.txt使用1 mb的块大小,则需要在上面的Map中输入1100个条目,而不是4个条目(这将需要名称节点中更多的内存)。同时,收回所有的块会更加昂贵,因为您将对datanode1进行1100次rpc调用,而不是4次。

相关问题