0%

HDFS文件块

HDFS Block 深度解析:为什么是 128MB?大了小了各有什么问题?

HDFS 把文件切成固定大小的块(Block)来存。这个块大小不是随便定的——128MB 这个数字背后有一套权衡逻辑。

理解 Block 的设计原理,你就理解了 HDFS 性能调优的底层逻辑:为什么小文件是大忌?为什么块大小会影响 MapReduce 任务的并行度?什么时候该调大、什么时候该调小?

Block 是什么?存数据的基本单位

HDFS 把每个文件切成固定大小的块,每个块独立存储在不同的 DataNode 上,通过多副本保证可靠性。

三个核心特性:

  • 固定大小:默认 128MB(Hadoop 2.x 起),可以调
  • 独立存储:一个文件的多个块分布在不同的 DataNode 上
  • 对用户透明:你操作的是完整文件,不用管它切成了几块

一个重要细节: 一个 10MB 的文件不会占满 128MB 的磁盘空间,它只占 10MB。块大小只是”切分上限”,不是”分配上限”。

块大小为什么是 128MB?核心是”寻址时间 vs 传输时间”

块大小的设计目标:让传输数据的时间远大于定位数据的时间。

寻址时间:NameNode 告诉客户端”这个块在哪台机器上”的时间,毫秒级(约 10ms)。

传输时间:从磁盘读取一个块并传输的时间。

如果块太小(比如 1MB),传输只要 0.01 秒,但寻址要 0.01 秒——寻址时间占 50%,效率极低

如果块太大(比如 1GB),传输要 10 秒,寻址时间占比只有 0.1%。但带来另一个问题:任务并行度下降(每个块对应一个 Map 任务,块太大任务数太少,集群闲着)。

128MB 是怎么来的?

块大小 传输时间(100MB/s 磁盘) 寻址时间占比 问题
64MB 0.64s ~1.5% Hadoop 1.x 默认,当时磁盘慢
128MB 1.28s ~0.8% Hadoop 2.x 默认,当前主流
256MB 2.56s ~0.4% 适合大文件场景(视频、日志归档)
1GB 10s ~0.1% 任务并行度下降

结论:128MB 是在”寻址开销可接受”和”任务并行度充足”之间取的平衡点。 磁盘速度越快,这个平衡点可以往上移(比如 256MB)。

块大小过小或过大,分别有什么问题?

块太小(比如 64MB 以下):

问题 具体表现
NameNode 内存爆炸 每个块约 150 字节元数据,块越多内存消耗越大
寻址开销高 大量小块意味着频繁的 NameNode 查询
Map 任务碎片化 每个块一个 Map 任务,任务太多调度开销大

块太大(比如 512MB 以上):

问题 具体表现
并行度下降 块太少,Map 任务太少,集群资源闲置
单个任务太重 一个 Map 处理 1GB 数据,失败了重算代价大
小文件浪费 100MB 文件如果是 1GB 块大小,元数据按 1 个块算,磁盘还是 100MB,问题不大,但块利用率低

实际场景怎么选:

场景 推荐块大小 原因
日志文件(几百 MB 到几 GB) 128MB 默认,适用绝大多数场景
视频/大文件(几十 GB) 256MB 减少块数量,降低 NameNode 内存压力
大量小文件(几 KB 到几 MB) 不靠调块大小解决 应该合并小文件,而不是调小块大小

怎么配置块大小

全局配置(hdfs-site.xml):

1
2
3
4
5
<!-- 配置默认块大小为 128MB(134217728 字节 = 128 * 1024 * 1024) -->  
<property>
<name>dfs.blocksize</name>
<value>128m</value>
</property>

支持的单位:k、m、g、t(比如 256m1g)。

单文件指定块大小(上传时覆盖):

1
hdfs dfs -D dfs.blocksize=64m -put local_file.txt /hdfs/path/

这个只对当前上传的文件生效,不影响全局。

副本数怎么配?

块大小管”切多大”,副本数管”存几份”,两个独立配置。

1
2
3
4
<property>
<name>dfs.replication</name>
<value>3</value>
</property>

也可以对单个文件改副本数:

1
hdfs dfs -setrep -R 2 /hdfs/path/file.txt

-R 表示递归修改目录下所有文件。

怎么查看 Block 信息

fsck:看块的分布和健康状态

1
hdfs fsck /hdfs/path/file.txt -files -blocks -locations

输出里能看到:

  • 这个文件分成了几个块
  • 每个块多大
  • 副本数是否达标(HEALTHY / UNDER_REPLICATED)
  • 每个块存在哪些 DataNode 上

stat:看块大小

1
2
hdfs dfs -stat "%o" /hdfs/path/file.txt
# 输出 134217728(128MB)

Web UI:

http://namenode:50070 → Utilities → Browse the file system → 选文件 → 看 Block 信息

几个常见问题

1. 小文件太多怎么办?

小文件的问题是元数据撑爆 NameNode 内存,不是磁盘空间。

解决方案:

  • hdfs dfs -getmerge 把小文件合并成大文件
  • 用 ORC / Parquet 这种列式格式打包,既压缩又减少文件数
  • 在数据采集阶段(比如 Flume)就做好文件滚动策略,别生成一堆几 KB 的文件

2. 块副本不足(UNDER_REPLICATED)怎么办?

先检查 DataNode 是不是有节点宕机或下线了。节点恢复了,HDFS 会自动复制补副本。

如果节点一直不够,可以考虑临时降低不重要文件的副本数:

1
hdfs dfs -setrep 2 /hdfs/path/temp_file.txt

3. 块大小调大了,但文件还是小,有影响吗?

一个 10MB 文件在 128MB 块大小下,只占 10MB 磁盘空间。元数据按一个块算(约 150 字节),不会因为块大小大就多占空间。

所以块大小调大主要影响大文件,对小文件没有负面影响,但也解决不了小文件的问题。

欢迎关注我的其它发布渠道