如果DataNode上的某个数据块损坏了,HDFS是如何发现并进行修复的?
在HDFS中,数据块(Block)损坏是非常常见的硬件故障(如磁盘坏道、静默数据损坏/Bit Rot等)。HDFS 的设计初衷就是“默认硬件会出错”,因此它拥有一套非常完善的自动化机制来发现和修复损坏的数据块。
整个过程可以分为三个主要阶段:发现(Detection)、汇报(Reporting) 和 修复(Recovery/Repair)。
第一阶段:如何“发现”数据块损坏?
HDFS 发现数据损坏的核心技术是 校验和(Checksum)。
当客户端向 HDFS 写入数据时,HDFS 会为每 512 字节的数据计算一个校验和(通常是 CRC32),并将这些校验和单独保存在 DataNode 的 .meta 文件中,与真实的数据块文件放在一起。
发现损坏通常有两种途径:
1. 客户端读取时触发发现(被动发现)
- 过程:当客户端(Client)从 DataNode 读取数据块时,DataNode 会同时把数据和对应的校验和发送给客户端。客户端在接收数据时会重新计算校验和,并与 DataNode 发来的校验和进行对比。
- 发现异常:如果两者不一致,客户端就会知道这个数据块已经损坏。
- 处理:客户端会向 NameNode 报告这个损坏的块,然后自动无缝切换到拥有该块其他副本的另外一台 DataNode 上继续读取数据,保证用户的读取任务不受影响。
2. DataNode 后台巡检发现(主动发现)
- 过程:如果某些数据长时间没有被客户端读取,磁盘自身的静默损坏就无法被及时发现。为了防止这种情况,DataNode 内部运行着一个后台线程——数据块扫描器(DataBlockScanner)。
- 发现异常:它会定期(默认是 504 小时,即 21 天,由
dfs.datanode.scan.period.hours配置)扫描该节点上的所有数据块,验证校验和。如果发现校验和不匹配,就会标记该数据块为损坏。
第二阶段:如何“汇报”损坏情况?
无论是客户端发现的,还是 DataBlockScanner 发现的,最终都需要让 HDFS 的“大脑”——NameNode 知道。
- 报告 NameNode:DataNode 会通过定期的 块汇报(Block Report) 或专门的损坏块报告机制,将损坏的数据块信息发送给 NameNode。
- NameNode 标记:NameNode 收到报告后,会在其内存的元数据中,将该 DataNode 上的这个特定副本标记为
Corrupt(损坏状态)。 - 隔离损坏块:被标记为损坏的副本不会再被 NameNode 分配给任何客户端读取请求。
第三阶段:如何进行“修复”?
NameNode 掌握全局状态,修复工作由 NameNode 统一调度,具体步骤如下:
1. 判定副本不足(Under-Replicated)
假设该文件的复制因子(Replication Factor)配置为 3。现在有一个副本损坏了,NameNode 计算出该数据块的健康副本数变成了 2(低于预期的 3)。此时,该数据块进入副本不足(Under-replicated)的队列。
2. 寻找健康副本与目标节点
NameNode 会从剩下的 2 个健康副本所在的 DataNode 中挑选一个作为数据源。同时,根据机架感知(Rack Awareness)策略和节点负载情况,挑选一个新的、健康的 DataNode 作为目标节点。
3. 下发复制指令
NameNode 自己并不传输数据。当作为数据源的那个健康 DataNode 向 NameNode 发送常规的心跳(Heartbeat)时,NameNode 会在心跳响应中夹带一条指令:“请把数据块 X 复制到目标 DataNode Y 上”。
4. 执行数据复制
健康的 DataNode 收到指令后,会在后台直接与目标 DataNode 建立连接,将健康的数据块复制过去。
5. 清理损坏副本
- 当目标 DataNode 成功接收并保存了数据块,它会向 NameNode 汇报自己拥有了这个块。
- 此时,NameNode 发现该数据块的健康副本数恢复到了 3。
- 接着,NameNode 会在下一次心跳中,向那个拥有损坏副本的 DataNode 发送删除指令。
- 该 DataNode 收到指令后,将本地磁盘上的损坏数据块及其
.meta校验文件物理删除。
总结
HDFS 处理数据块损坏的过程是完全自动化且对用户透明的。
用户或应用程序在读取数据时不会因为某个节点的磁盘坏道而中断任务。HDFS 通过 “校验和 -> 发现异常 -> 报告 NameNode -> 隔离坏块 -> 异步复制新副本 -> 删除坏块” 这一套行云流水的机制,确保了系统的高可用性和数据的极高可靠性。