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 会重新添加副本,重新负载副本
- 客户端询问 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服务器的瓶颈)
- 多个客户端并发的向同一份文件更新操作(除了追加)