如果您有不可拆分的文件,那么您最好使用更大的块大小 - 与文件本身一样大(或更大,没有区别)。
如果块大小小于整体文件大小,那么您可能会遇到所有块并不都在同一个数据节点上并且您丢失数据局部性的可能性。这不是可拆分文件的问题,因为将为每个块创建一个映射任务。
至于块大小的上限,我知道对于某些旧版本的 Hadoop,限制是 2GB(超过该块内容是无法获得的) - 请参阅https://issues.apache.org/jira/browse/HDFS- 96
存储具有较大块大小的较小文件没有缺点 - 为了强调这一点,考虑一个 1MB 和 2 GB 的文件,每个文件的块大小为 2 GB:
- 1 MB - 1 个块,名称节点中的单个条目,1 MB 物理存储在每个数据节点副本上
- 2 GB - 1 个块,名称节点中的单个条目,每个数据节点副本上物理存储 2 GB
因此,除了所需的物理存储之外,名称节点块表没有缺点(两个文件在块表中都有一个条目)。
唯一可能的缺点是复制较小块与较大块所需的时间,但另一方面,如果数据节点从集群中丢失,则任务复制 2000 x 1 MB 块比单个块 2 GB 块慢.
更新 - 一个有效的例子
看到这会引起一些混乱,这里有一些工作示例:
假设我们有一个具有 300 MB HDFS 块大小的系统,为了使事情更简单,我们有一个只有一个数据节点的伪集群。
如果你想存储一个 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
请注意,文件不能完全被 300 MB 整除,因此文件的最终块的大小是文件的块大小的模数。
现在,如果我们对小于块大小的文件(例如 1 MB)重复相同的练习,并查看它将如何存储在数据节点上:
/local/path/to/datanode/storage/0/blk_000000000000005 1 MB
再次注意,存储在数据节点上的实际文件是 1 MB,而不是200 MB 的文件,299 MB 的零填充(我认为这是混乱的来源)。
现在,块大小确实影响效率的地方在于名称节点。对于上面的两个例子,name node 需要维护一个文件名的映射,到块名和数据节点位置(以及总文件大小和块大小):
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 的块大小,则上述映射中需要 1100 个条目而不是 4 个(这将需要名称节点中的更多内存)。此外,撤回所有块会更昂贵,因为您将对 datanode1 进行 1100 次 RPC 调用而不是 4 次。