GFS 笔记 - MIT-6.824

Posted by cwen 2017-08-31

GFS是一个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用。它运行于廉价的普通硬件上,并提供容错功能。它可以给大量的用户提供总体性能较高的服务…

什么是一致性?

  • 一个正确性条件
  • 当存在副本和程序并发访问的时候,一致性是很重要的
    • 如果一个应用进行写操作,那么之后的读操作可以观察到什么?如果这个读操作来自其他应用程序又会看到什么?
  • 弱一致性
    • read() 可能返回旧的数据 — 不是最新写入的数据
  • 强一致性
    • read() 总是返回最新写入的数据
  • 一般的权衡
    • 强一致性对程序的写操作(application writers)表现不错
    • 强一致性对性能有一定的影响
  • 更多的正确性条件(通常被称为一致性模型)

“理想” 的一致性模型

  • 一个有副本的文件系统和一个没有副本的文件系统表现的一样,就像许多客户端访问痛一台机器上的单独磁盘
  • 如果一个程序写数据,那么之后的就可以读到之前写的数据
  • 如果两个程序并发的写同一个文件呢?
    • 在文件系统中这种行为经常是未定义的 —— 文件也许会混合两个写操作的内容
  • 如果两个程序并发的写同一个目录呢?
    • 一个一个顺序执行

去实现理想的一致性的挑战

  • 并发
  • 机器失败
  • 网络分割

为什么去克服这些挑战是困难的?

  • clients 和 servers 之前要求通信,可能会消耗性能
  • 协议可能变得复杂 — 后面的课程我们会看到很难实现正确的系统

GFS 中的主要挑战

  • 存在许多机器,所有机器出现故障是很常见的现象,假设一台机器一年出错一次,那么当存在1000台机器的时候,每天都有三台机器出现问题。
  • 高性能:很多并发的读写操作,Map/Reduce工作会从 GFS 读取数据,然后保存最后的结果,注意:保存的不是中间临时文件。
  • 有效的使用网络

高层次的设计

  • 定义目录、文件、命名、打开/读/写操作,但是不是符合posix标准
  • 成千上百的带有硬盘的 linux 服务器
    • 存储64MB的块(an ordinary Linux file for each chunk)
    • each chunk 在三个服务器上存在副本
    • Q: 为什么三副本?
    • Q:除了数据的可用性,三副本方案给我们带来了什么?对热点文件的读取做负载均衡
    • Q: 为什么不只存储一份文件到 RAID 磁盘? RAID 磁盘不是常用品,我们想给整台机器做容错,而不是仅仅针对存储系统。
    • Q: 为什么 chunks 这么大?
  • GFS 的 master server 知道目录层级
    • 对于目录而言,知道里面有哪些文件
    • 对于为难而言,知道哪些数据块服务器存储了相关的64MB大小数据块
    • master server 在内存里面保存状态信息,每个chunk在主控服务器上面只保存64bytes大小的metadata
    • master server 有为元数据准备的可回收数据库,可以从断电故障后快速恢复
    • 同时存在备份的主控服务器(shadow master),数据略比主控服务器服务器延迟,可以被提升为主控服务器

基础的文件操作

  • 客户端读操作
    • 客户端发送文件名和偏移量到 master
    • 主控服务器回复带有相关 chunk 的数据块服务器集合,相应信息包括版本信息,客户端临时缓存这些信息,然后访问最近的数据块服务器,版本检查,如果版本是不正确的,重新从 master 获取最新的数据
  • 客户端 append
    • 客户端询问 master 去存储在什么地方
      • 如果文件大小超过64MB,master 也许会选择一些新的数据块服务器
      • master 把 chunk servers 和版本信息返回给客户端,其中一个 chunk 是 primary
    • 客户端把数据推送的副本
      • 副本构成一个链表
      • 链表涉及到网络拓扑
      • 允许快速复杂
    • 当数据都在所有的 chunk servers 时候客户端与 primary server 沟通
      • primary 分配序列号
      • primary apply 本地的修改
      • primary 转发请求到副本
      • 当 primary 收到所有副本的 ack 后,返回给客户端
    • 如果一个副本是没有响应,客户端将要重试
    • 如果 master 没有重置 lease, master 可以重新指定新的 master,
    • 如果副本的数量小于某个值的时候,master 会重新添加副本,重新负载副本

GFS 达到了理想中的一致性了吗?

两种情况:目录和文件

目录 yes,but…

  • yes: 强一致性 (仅有一个副本)
  • but:
    • Master 有可能挂掉并且 GFS 是不可用的
    • shadow master 可以提供只读操作,但是它返回老的数据
    • Q: 那写操作呢? 脑裂现象

文件:不一定

  • 带有原子追加的突变
    • 一个文件可以有重复的 enties 和空洞,如果 primary 与一个副本连接失败,primary 会给客户端报一个错误,客户端重试并且 primary 选择一个新的偏移量,记录可能是重复写入,其他的副本可能存在空洞
  • 一个不幸运的客户端可能在短时间内读到一个老的数据
    • 一个失败的突变导致 chunks 的不一致,primary chunk 更新 chunck 但是失败了并且副本数据过时了
    • 一个客户端可能去读一个没有跟新数据的 chunk
    • 当客户端刷新 lease 的时候,他将获得到最新版本
  • 没有原子追加的突变
    • 不同客户端的数据可能被混合
    • 如果你是在使用原子追加或是临时文件和自动重命名,并发的写在不同的 Unix 机器上可能导致奇怪的现象

作者主张弱一致性对app而言不是什么大问题

  • 大多数文件更新操作只是追加
    • 应用程序可以使用添加记录中的uid判断是否重复
    • 应用程序也许只是读取到少量的数据(而不是不新鲜的数据)
  • 应用程序可以使用临时文件和原子的重命名操作

性能

  • 巨大的读操作总吞吐量(3个副本,striping ???)
    • 125 MB/sec
    • 接近网络饱和状态
  • 写入不同的文件低于可能的最大值
    • 作者怪网络堆栈
    • chunk直接的复制操作会引起延迟
  • 并发追加同一份文件
    • 被服务器存在的最新的chunk所限制

总结

  • GFS使用的比较重要的容错技术riz
    • 操作日志、检查点
    • chunk之间的主备备份(but with consistencies??)
    • 我们将会在其他系统中也看到这里
  • 哪些在GFS中工作很好
    • 巨大的顺序读写操作
    • 追加
    • 巨大的吞吐量
    • 数据之间的容错
  • 哪些在GFS中做的不怎么好
    • master服务器的容错
    • 小文件(master服务器的瓶颈)
    • 多个客户端并发的向同一份文件更新操作(除了追加)

参考

  1. The Google File System
  2. 6.824-nodes
  3. GFS案例学习