作者:Sanjay Ghemawat
          Howard Gobioff
          Shun-Tak Leung
翻译:tinyfool

5.2 数据完整性

每个块服务器利用校验和来检查存储的数据是否损坏。一个拥有数百台机器数千个硬盘的GFS集群,硬盘故障带来的数据损坏和丢失是非常频繁的。(See Section 7 for one cause.)我们可以利用块的其他副本修复损坏,但是通过比较多台块服务器的数据来检查损坏是非常不可行的。而且,不一致的副本可能是合法的:GFS操作的语意,特别是前面讨论过的原子性的记录添加,不保证产生完全一致的副本。所以,每个块服务器必须通过校验和,独立的验证它自己拥有的拷贝的数据完整性。

块被分为64KB的大小。每个有一个对应的32位的校验和。和其他元数据一样,校验和保存在内存,持续化存储在日志里,与用户数据是分离的。

不管是对客户机还是其他的块服务器,在读取操作中,块服务器在返回任何数据之前验证读取范围的数据的校验和。这样块服务器就不会把损坏的数据传播给其他机器。如果块和记录的校验和不符,块服务器给请求者返回一个错误信息,然后把这个不匹配报告给主服务器。作为回应,请求者读取其他的副本,而主服务器从其他的副本克隆这个块。一个好的新块布置好后,主服务器指导报告不匹配的那台块服务器删除这个副本。

校验和对读取性能影响不大,基于几个原因。因为我们的读取范围至少是几个块,而我们只需要读取很少的额外数据去做验证。GFS客户机代码更进一步降低了负载,因为它尽量在校验和块的边界对齐读取。而且,校验和的查询和比较都在块服务器完成,不需要任何I/O,而且校验和的计算通常跟I/O同步进行。

在追加到文件尾的写入操作(而不是覆盖现有数据的写入操作),校验和的计算被严重的优化,因为这类操作是我们负载中最优先的。我们只是增量更新最后一块追加记录的校验和,用所有的追加来的新校验和块来计算新的校验和。即使最后一个校验和块破坏了,而我们无法检测到它,但是这样新的校验和就不会符合存储的数据,那么我们就可以在下次读的时候检测到这个损坏了。

相对而言,如果写入覆盖块的已存在区域,我们必须读取并且验证写入区域的第一个和最后一个数据块,然后执行写操作,最后计算和记录新的校验和。如果在写之前,我们不验证第一个和最后一个数据块,那么新的校验和可能会隐藏位于那些没有被覆盖区域的数据错误。

在空闲期间,块服务器可以扫描并验证不活跃块的内容。这就使我们可以检查那些很少被读取的块。一旦检测出损坏,主服务器就可以创建一个新的没有损坏的副本,并删掉损坏的副本。这就避免了一个不活跃的坏块骗过主服务器,让之以为块有足够的好的副本。


<< 5.1.3 主节点复制 | 5.3 诊断工具 >>