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


记录追加操作是修改操作中的一种,遵循 3.1 中介绍的控制流程,只在 Primary 上有一些额外的逻辑 。客户端把数据推送到文件最后一个块的所有的副本上,然后将向 Primary 发送它的请求 。Primary 会检查这次追加操作是否使块的大小超过了最大尺寸(64MB) 。

  • 如果超过,它将把这个块填充满,通知所有的 Secondary 副本进行相同的操作,并回复客户端表明这个操作将在下一个块上重新执行 。(记录追加操作的数据大小严格控制在最大尺寸的 1/4 以内 , 以确保最坏情况下碎片的数量在一个可接受范围 。)
  • 通常情况下,如果记录不超过最大尺寸,Primary 将数据追加到它的副本上,然后通知Secondary 把数据写到与 Primary 相同的位置上 , 最后回复客户端操作成功 。
如果在任意一个副本上的记录追加失败,客户端将重试这个操作 。因此,在同一个块的副本上可能包含不同的数据,包括同一个记录的全部或部分的重复数据 。GFS 不保证写入的数据在字节上完全相同,它只保证作为一个原子单元至少被写入一次 。这个特性能够通过简单的观察得到:如果操作执行成功 , 数据肯定被写入到了某些块副本的相同位置 。此外 , 在这之后,所有副本至少都达到了记录尾部的长度 。因此,即使一个不同的副本成为了 Primary,以后的任何记录也都将被放置在更大的偏移位置或者是一个不同的块上 。在我们的一致性保障方面,记录追加操作成功的写入数据的区域是被定义的(因此是一致的),反之,介于中间状态的区域是不一致的(因此是未定义的) 。我们的应用使用在 2.7.2 讨论的方法处理这种不一致的区域 。
3.4 快照快照操作几乎瞬间为一个文件或一个目录树(源)创建一个拷贝 , 并且不会对正在进行的其它操作造成任何影响 。我们的用户使用它为一个巨大的数据集创建一个拷贝分支(而且经常递归的对拷贝进行拷贝) , 或者是在尝试变化之前对当前的状态创建检查点,之后可以轻松的进行提交或回滚 。
像 AFS 一样,我们使用标准的写时拷贝(Copy-On-Write)技术来实现快照 。当 Master 接收到一个快照请求时,它先取消快照相关的文件块的所有租约 。这确保了任何后面对这些块的写操作将需要与 Master 进行交互,以获取租约的持有者 , 这将为 Master 提供一个为块创建一个新拷贝的机会 。
写时拷贝:在被修改时才真正执行拷贝
在租约被取消或者过期后,Master 将这些操作记录到磁盘,然后以复制源文件或目录树元数据的方式来在内存上执行这些日志记录 。新创建的快照文件与源文件指向相同的块 。
在快照操作后,我们以下面的方式来执行复制写入:
  1. 客户端第一次想要向块 C 中写入数据前,它将向 Master 发送一个请求来查找当前的租约持有者 。
  2. Master 注意到块 C 的引用计数大于 1,它将推迟回复客户端的请求,并选择一个新的块句柄 C’,然后通知每个拥有块 C 副本的块服务器,创建一个新的块 C’ 。通过在同一个块服务器上创建一个新的块,我们能确保这个拷贝是本地的,不需要通过网络进行的(我们的磁盘速度是100MB以太网链路的3倍) 。
  3. 从这点上看,请求的处理不会与其它的块处理有差别:主节点将新块 C’ 的租约授予其中一个副本,并回复客户端 , 客户端能够进行一般的写操作 , 并不知道这个块是从一个已存在的块上创建出来的 。
4. Master操作Master 完成了以下这些工作:
  1. 执行所有的命名空间操作 。
  2. 管理整个系统内的所有块的副本 。
    • 决定块的存储位置 。
    • 协调系统范围内的各种行为以保障块能够有足够的副本 。
    • 均衡所有块服务器的负载 。
    • 以及回收不再使用的存储空间 。
4.1 命名空间管理与锁许多 Master 操作会占用较长时间:例如,一个快照操作必须撤销所有进行快照的块所在块服务器的租约,我们不想推迟正在进行的其它 Master 操作,因此,我们允许多个操作同时进行,并使用命名空间区域的锁来确保这些操作按适当的顺序执行 。
不像许多传统的文件系统那样,GFS 没有一个目录数据结构来列出这个目录下的所有文件,也不支持对文件和目录的别名操作(如 , Unix术语中的硬链接或符号链接) 。GFS 的命名空间逻辑上表现为一个将全路径名映射为元数据的查询表 。利用前缀压缩,这个表能够高效的存储在内存中 。每个命名空间树中的节点(无论是一个绝对文件名还是一个绝对目录名)都有一个与之关联的读写锁 。

推荐阅读