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

2.7.1 GFS的保证

文件命名空间的修改(例如,文件创建)是原子性的。他们仅受主服务器的控制:命名空间锁定保证了原子性和正确性(4.1章);主服务器的操作日志定义了这些操作的全局总顺序(2.6.3章)。

记录追加
串行成功 已定义 已定义
部分不一致
并行成功 一致但是未定义
失败 不一致
表1 操作后的文件状态

数据操作后文件范围的状态取决于操作的类型,是否成功,以及是否是同步操作。表1概述了这些结果。如果所有客户端,不管从哪个副本读取,看到的数据都一样,那么我们说文件区域是一致的。如果数据操作后,文件范围是一致的,且客户端可以知道到操作写入了什么内容,那么文件区域是已定义的。当数据操作完成,同步写入者间没有冲突,那么影响的文件范围就是已定义的(隐含了一致性):所有的客户端一直都可以看到写入的内容。成功的同步操作后,文件范围未定义,但是是一致的:所有的客户端看到同样的数据,但是任何一个操作的写入内容都不会被表现出来。通常情况下,文件范围内包含了混杂的来自多个操作的数据片段。一个失败的操作,会让文件范围不一致(所以也是未定义的):不同的时间不同的客户端会看到不同的数据。后面我们将描述我们的应用如何区分已定义和未定义的范围。应用程序没有必要进一步区分未定义范围的不同类型。

数据操作可以是写或者记录追加。写操作会把数据写在应用程序指定的偏移位置。即使是在同步进行多个操作时,记录追加至少可以把数据(记录)原子性的追加到文件中一次,但是偏移位置是GFS选择的(3.3章)。(相比而言,通常说的追加写入的偏移位置在文件的尾部。)偏移位置被返回给客户端,用来标明包含记录的已定义范围的起点。此外,GFS可能会在中间插入填充数据或者记录的副本。他们占用那些被认定是不一致的范围,通常他们比用户数据的量小的多。

在一系列成功的操作后,被操作的数据范围被保证为已定义的,并且包含最后一次操作写入的数据。(a) GFS对块的多个副本采用一样的顺序进行操作(3.1章)。(b)并使用块版本号来检测副本是否因为它所在的块服务器当机(4.5章)而错过了某些操作,而失效了。失效的副本不会再被任何操作涉及,也不会被主服务器作为块位置告知客户端。他们会优先被垃圾收集。

由于客户端缓存块位置,所以在信息刷新前,他们有可能从一个失效的副本读取数据。时间窗口由缓存的超时以及文件的下一次打开时间决定,文件打开后会清除缓存中与文件有关的所有块信息。而且由于我们的文件大多数都是只进行追加的,所以一个失效的副本通常返回一个提前结束的块而不是过期的数据。读取者重新尝试并联络主服务器后,就会立刻得到当前的块位置。

成功操作很久以后,组件的失效当然也可以损坏或者毁掉数据。GFS用主服务器和块服务器之间的定期握手来找到失效的块服务器,用校验和来检测数据的损坏(5.2章)。一旦发现问题,数据会尽快从有效的副本中恢复出来(4.3章)。只有一个块的所有副本在GFS做出反应之前,全部丢失,这个块才会不可逆转的丢失,而通常GFS的反应是在几分钟内的。即使在这种情况下,块不可用,而不是损坏:应用程序会收到清晰的错误信息而不是损坏的数据。


<< 2.7 一致性模型 | 2.7.2 程序的实现 >>