HDFS DataNode 工作机制:数据怎么存、状态怎么报、坏了怎么办
DataNode 是 HDFS 里真正存数据的节点。NameNode 管”账本”,DataNode 管”货”。
但它不只是”存”就完了——还要定期向 NameNode 报平安、汇报自己手里有哪些数据块、自己检查数据有没有坏。这套机制保证了 HDFS 在廉价硬件上仍然可靠。
DataNode 的三大职责
| 职责 | 具体工作 |
|---|---|
| 存数据 | 把 Block 以文件形式存在本地磁盘上 |
| 报状态 | 定期告诉 NameNode “我活着”、”我手里有这些块” |
| 自检 | 检查自己存的数据有没有损坏,坏了就上报 |
启动阶段:注册 + 第一次汇报
sequenceDiagram
participant DN[DataNode]
participant NN[NameNode]
DN->>NN: 发送注册请求(包含节点 ID、存储目录等信息)
NN->>DN: 验证注册信息,返回注册成功响应
DN->>DN: 扫描本地存储目录,收集所有数据块信息(Block ID、大小、校验和)
DN->>NN: 发送完整块报告(Block Report),包含所有块的元数据
NN->>DN: 确认块报告,更新集群块映射信息
Note over DN,NN: 初始化完成,DataNode 进入常态运行
DataNode 启动时做三件事:
1. 注册
向 NameNode 发送注册请求,包含节点 ID 和存储目录信息。NameNode 验证通过后,DataNode 正式加入集群。
DataNode 的节点 ID 存在本地文件里(dfs.datanode.data.dir/current/VERSION),每次启动用同一个 ID,避免 NameNode 把它当成新节点。
2. 扫描本地磁盘
扫描 dfs.datanode.data.dir 配置的所有目录,收集自己手里有哪些 Block。
3. 发送完整块报告
把扫描到的所有 Block 信息一次性发给 NameNode。NameNode 收到后更新内存中的块映射。
第一次块报告的数据量很大(一个 DataNode 可能有几万甚至几十万个 Block),所以 DataNode 启动后需要一点时间才能完成初始化。
常态运行:心跳 + 增量报告
启动完成后,DataNode 进入日常运行状态,主要做两件事:
1. 心跳(Heartbeat)——“我还活着”
默认每 3 秒向 NameNode 发一次心跳。NameNode 通过心跳知道这个节点还活着,同时在心跳响应里附带指令——“把块 A 复制一份到节点 X”、”把块 B 删掉”。
心跳停了,NameNode 就知道这个节点可能挂了。
2. 增量块报告——“我手里的块有变化”
完整块报告只在启动时发一次,日常只发送有变化的块——新增的、删除的、修改的。默认每 6 小时发一次。
这两种报告的频率对比:
| 报告类型 | 频率 | 内容 |
|---|---|---|
| 心跳 | 3 秒 | 节点存活状态 + 接收指令 |
| 增量块报告 | 6 小时 | 自上次报告后有变化的块 |
| 完整块报告 | 仅启动时 | 所有块(一次性) |
数据完整性保障:校验和机制
DataNode 存的数据可能会坏——磁盘坏道、网络传输错位、硬件老化。HDFS 靠校验和(CheckSum)来检测数据是否损坏。
原理很简单:
- 写入数据时,每写一个 Block,同时计算一个校验和(默认 CRC32C 算法),存成一个
.meta文件 - 读取数据时,重新计算校验和,跟
.meta文件里的对比 - 对不上 → 数据坏了
验证时机:
- 读取时验证:客户端读数据时,DataNode 自动校验
- 定期扫描:DataNode 后台线程定期扫描所有 Block(默认每 3 周一次)
发现损坏了怎么办?
DataNode 把坏块标记为损坏,向 NameNode 报告。NameNode 从其他副本复制一份到这个节点,恢复副本数。
这个机制的意义: HDFS 用的是廉价硬盘,硬盘会坏。校验和机制让 DataNode 自己发现坏块并触发修复,不需要人工介入。
故障检测:NameNode 怎么知道 DataNode 死了?
DataNode 如果超过一定时间不发送心跳,NameNode 就把它标记为”死亡”。
超时计算公式:
1 | 超时时间 = 2 × recheck-interval + 10 × heartbeat-interval |
默认值:
heartbeat.interval= 3 秒recheck-interval= 5 分钟(300000 毫秒)
默认超时 = 2 × 300 秒 + 10 × 3 秒 = 630 秒(10.5 分钟)
也就是说,DataNode 超过 10.5 分钟没发心跳,NameNode 就判定它挂了。
为什么不设更短? 网络抖动可能导致节点”假死”,设太短会频繁触发副本复制,浪费资源。
故障恢复:节点挂了,数据怎么办?
NameNode 判定一个 DataNode 死亡后,自动启动恢复流程:
- 把这个节点上的所有 Block 标记为”副本不足”(Under-Replicated)
- 对每个副本不足的 Block,找其他有副本的节点复制一份
- 确保每个 Block 的副本数恢复到配置值(默认 3)
这个过程的代价不小——大量数据需要跨节点复制,网络带宽会吃紧。所以一个稳定运行的集群,DataNode 不要频繁上下线。
存储目录:数据怎么放在磁盘上
DataNode 的数据存储目录通过 dfs.datanode.data.dir 配置,支持多目录:
1 | <property> |
多目录的好处:
- 数据均匀分布到各磁盘,避免单盘过载
- 一块磁盘坏了,只影响那上面的 Block,其他磁盘不受影响
目录结构:
1 | /hadoop/hdfs/data/current/ |
Block 文件分散在 subdir0、subdir1… 子目录下,避免单个目录下文件数量过多导致性能下降。
几个实际运维中的注意点
1. 磁盘满了怎么办?
DataNode 磁盘写满,NameNode 不会自动处理,但 DataNode 会拒绝写入新块。监控磁盘使用率,超过 80% 就该考虑扩容或清理数据。
2. 块报告太大,NameNode 处理不过来?
如果集群规模很大(上千节点),完整块报告同时发送会压垮 NameNode。可以通过 dfs.blockreport.split.threshold 把块报告拆成小块分批发送。
3. DataNode 启动慢?
启动时要扫描所有磁盘,扫描几百万个 Block 可能需要十几分钟。正常现象,不要以为卡住了就重启。
4. 副本不足报警怎么处理?
hdfs fsck / 会显示有多少 Block 副本不足。如果持续存在,说明 DataNode 节点不够或者有节点故障了。先检查集群节点状态,再考虑增加节点或降低副本数。