摘录自《Hadoop 权威指南》—— 第四版
Hadoop 用户希望系统在存储和处理时不会丢失或损坏任何数。尽管磁盘或网络上的每个 I/O 操作不太可能将错误引入自己正在读/写的数据中,但是如果系统中需要处理的数据量大到 Hadoop 的处理极限时,数据被损坏的概率还是很高的。
监测数据是否损坏的常见措施是,在数据第一次引入系统时计算校验和(checksum)并在数据通过一个不可靠的通道进行传输时再次计算校验和,这样就能发现数据是否损坏。如果计算得到的校验和
和原来的校验和不匹配,就认为数据已损坏。注意,该技术只能检测数据错误,另外校验和也是可能损坏的,不只是数据,但由于校验和比数据小得多,所以损坏的可能性非常小。
常用的错误检测码是 CRC-32(32位循环冗余校验),任何大小的数据输入均计算得到一个 32 位的整数校验和。Hadoop ChecksumFileSystem 使用 CRC-32 计算校验和,HDFS 用于校验和计算的则是一个更有效的变体 CRC-32C。
HDFS 的完整性
HDFS 会对写入的所有数据计算校验和,并在读取数据时验证校验和。它针对每个由 dfs.bytes-per-checksum 指定字节的数据计算校验和。默认情况下位 512 个字节,由于 CRC-32 校验和是 4 个字节,所以存储校验和的额外开销低于 1%。
datanode 负责在收到数据后存储该数据及其校验和之前对数据进行验证。它在收到客户端的数据或复制其它 datanode 的数据时执行这个操作。正在写数据的客户端将数据及其校验和发送到由一系列 datanode 组成的管线,管线中最后一个 datanode 负责验证校验和。如果 datanode 检测到错误,客户端便会收到一个 IOException 异常的一个子类,对于该异常应以应用程序特定的方式来处理,比如重试这个操作。
客户端从 datanode 读取数据时,也会验证校验和,将它们与 datanode 中存储的校验和进行比较。每个 datanode 均持久化保存有一个用于验证的校验和日志(persistent log of checknum verification),所以它知道每个数据块的最后一次验证时间。客户端成功验证一个数据块后,会告诉这个 datanode,datanode 由此更新日志。
保
存
这
些
统
计
信
息
对
于
检
测
损
坏
的
磁
盘
很
有
价
值
。
\color{blue}{保存这些统计信息对于检测损坏的磁盘很有价值。}
保存这些统计信息对于检测损坏的磁盘很有价值。
不只是客户端在读取数据块时会验证校验和,每个 datanode 也会在一个后台线程中运行一个 DataBlockScanner,从而定期验证存储在这个 datanode 上的所有数据块。
该
项
措
施
是
解
决
物
理
存
储
媒
体
上
位
损
坏
的
有
力
措
施
。
\color{blue}{该项措施是解决物理存储媒体上位损坏的有力措施。}
该项措施是解决物理存储媒体上位损坏的有力措施。
由于 HDFS 存储着每个数据块的复本(replica),因此它可以通过数据复本来修复损坏的数据块,进而得到一个新的、完好无损的复本。基本思路是:
- 客户端在读取数据块时,如果检测到错误,首先向 namenode 报告已损坏的数据块及其正在尝试读操作的这个 datanode,再抛出 ChecksumException 异常;
- namenode 将这个数据块复本标记为已损坏,这样它不再将客户端处理请求直接发送到这个节点,或尝试将这个复本复制到另一个 datanode;
- 之后,它安排这个数据块的一个复本复制到另一个 datanode,如此一来,数据块的复本因子(replication factor)又回到期望水平;
- 此后,已损坏的数据块复本便被删除;