The Google File System 翻译和理解(13)


5.2 数据完整性每个块服务器使用校验和来探测存储的数据是否被损坏 。考虑到一个 GFS 集群经常由数百个机器上的数千块磁盘组成,由于磁盘的损坏而造成的读和写路径上的数据损坏或丢失是很常见的 。(其中的一个原因见7.1节)我们能够使用块的其它副本来进行恢复,但是无法通过不同块服务器上的副本的比较来探测出数据块是否损坏 。此外,不同的副本之前有分歧可能是合理的:GFS 修改操作的语法,特别是之前讨论过的原子追加操作,本身就不能保证所有副本都相同 。因此,每个块服务器必须独立的通过校验和验证它所拥有的拷贝是否合法 。
一个块被分割成 64KB 大小的 block,每个 block 都有一个对应的 32bit 校验和 。像其它元数据一样,校验和保存在内存中,并通过日志永久存储,与用户数据分开 。
对于读操作,在把数据返回给请求者之前,块服务器要验证读范围内所有数据 block 的校验和,因此,块服务器不会将损坏的数据传播到其它机器上 。如果一个 block 与记录的校验和不匹配,块服务器会返回给请求者一个错误,并向 Master 报告这个错误 。在响应中,请求者将从其它的副本读取数据,同时,Master 将从其它副本上克隆这个块 。在一个新的可用的副本复制完毕后,Master 会通知报告错误的块服务器删除出错的副本 。
校验和对读操作几乎没有影响,原因有几个:

  • 因为大多数的读操作至少需要读取几个块,我们只需要读取一小部分额外的数据用于验证验证和 。
  • GFS 客户端代码通过试图将读操作对齐到校验和的 block 边界上,大大减小了验证的开销 。
  • 此外,块服务器上的校验和查询和对比不需要任何 I/O 就能完成,校验和的计算可以和 I/O 操作同时进行 。
校验和计算针对在块尾部进行追加写操作做了很大的优化(相对于覆盖已有数据的写操作) 。我们仅增量更新最后一个不完整的块的校验和,并用追加的新的校验和来计算 block 新的校验和 。即使最后一个不完整的校验和已经被损坏,并且我们现在没有探测出来,新的校验和将不匹配存储的数据,当这个块下一次被读取时,就会检测出数据已经损坏 。
相反的,如果写操作覆盖块中已经存在的一部分,我们必须读取并验证要被覆盖的这个范围内的第一个和最后一个 block,然后执行写操作,最后计算并记录新的校验和 。如果我们在覆盖它们之前不进行这一对验证,新的校验和可能会隐藏没有被覆盖区域的错误 。
在空闲的时候,块服务器能浏览和验证不活跃的块,这允许我们探测很少被读取的块的数据损坏 。一旦损坏被探测到,Master 就能创建一个新的没有损坏的副本,并删除已损坏的副本 。这能够防止不活跃的、已损坏的块欺骗 Master,使 Master 认为它是块的一个可用的副本 。
5.3 诊断工具在问题隔离、调试和性能分析方面,详尽的、细节的诊断日志给我们很大的帮助 。如果没有日志,我们很难理解短暂的、不重复的机器间的消息交互 。GFS 服务器生成诊断日志用于记录许多关键的事件(如块服务器启动和关闭),以及所有的远程调用(RPC)的请求和响应 。这些诊断日志能够被自由的删除,不会给系统带来任何影响 。然而,在空间允许的情况下,我们会尽量保存这些日志 。
远程调用(RPC)日志包括网络上所有的请求和响应,除了文件数据被读取或写入 。通过匹配请求和响应,以及核对其它机器上的 RPC 记录,我们能重建这个交互历史用于诊断错误 。这些日志也能用于跟踪负载测试和性能分析 。
记录日志所造成的性能影响很小(远小于它带来的好处),因为这些日志异步的、顺序的被写入 。最近的事件也会保存在内存中,可用于持续的在线监控 。

经验总结扩展阅读