GFS论文发表距今已经十几年了,据之开源的hdfs也已经在业界得到了广泛应用。为了取得分布式系统的真经,拜读一下这篇经典论文。
重要假设
- 软硬件失败乃家常便饭
- 我们写大文件,不屑小文件
- 文件改动的主流是追加新数据,随机写是非主流
- 一旦写完,仅会读取
系统结构
先整一张比较风骚的图
再看一张正经图
那么你应该可以看出,系统就由四部分构成了
- 文件由固定大小的chunk (64 MB) 组成
- 每个chunk都会从master那得到一个句柄,和一个uuid
- 存为linux文件
一个 Master
- 保存所有metadata
- 与chunkserver周期性通信
多个 Chunkserver
- 在本地磁盘存储chunk
- 不缓存chunk
多个客户端
- 从master请求metadata
- 从chunkserver读写数据
single master
优点
一目了然,真简单
风险
- 单点故障
- 系统瓶颈
解决方案
- 尽量少参与实际工作,专心当领导
- 大的chunk设置,64MB(这样实际管理的metadata量减小,并且全在内存中,加快处理速度)
- 不进行实际数据操作,只管理metadata,在客户端请求时将metadata缓存到客户端
- 有数据改动时,授权主副本全权操作,后面会提到chunk lease机制
- 分发操作记录(operation log)到多台机器,一旦挂掉,其它机器可取而代之
主要功能
- 存metadata
- 命令空间(类似文件路径)管理/加锁
- 监管chunkserver
- 垃圾回收
- 生成chunk
- 副本低于指定目标时,查漏补缺
- 负载均衡,平衡和优化磁盘使用率及负载
metadata
- 全部存储于master
- 文件及chunk命名空间
- 文件到chunk的映射
- chunk所有副本的地址
- 全部加载于内存
- 64字节/chunk
- 快速
- 操作记录
- 持久化于本地磁盘
- 分发多份副本
- checkpoints(快速复原)
mutation
mutation原意为突变,此处意为文件变更,是GFS设计的关键和复杂之处,也是其一致性模型要处理的核心问题。文件的变更有三种可能。
- 文件命名空间变更 ,只在master一处发生,通过锁即可保证原子性和正确性
- 随机写,write
- 文件追加,append
那么文件的变更,主要就在于如何处理write和append两种操作了。write和append大体类同,先说write,再说append就简单了。
write操作
论文里面详细描述了写的流程,不再赘述,关键在于master指定了要被更改chunk的primary replica(首席副本,假定其所在主机为P),并给了它一个lease,有时间限制,可以视之为令牌。此时P就可以全权执行写操作了,如果有并发写入,P就内定一个顺序,然后其它副本也会按照这个顺序写入,这样当所有副本写入完成后,它们的内容就完全一样了。各个副本写完后回复primary replica,然后P应答client写入成功或者失败。
其实从上面可以看到,master只要指定了primary replica,下面就垂拱而治了。这极大地减轻了master的负担,使得单master可以支持那么大的集群。
下面再给大家上两张更清晰的写流程图:
client下发数据:图中粗的实线代表数据流,左右的client代表并发写入
client命令primary replica(主副本)写入,后者确定写入顺序,让其它副本照办
append操作
与写入不同,append操作时,client只要提供数据即可,写入时的offset是由primary replica确定的。其它基本一致。
那么,怎么理解“append at least once atomically”,至少会有一次原子性的追加操作。也就是说,如果有副本失败,那么client端会重试,则某些副本可能会多次追加数据,也就是说在某些副本上,数据可能有重复。但是对于所有的副本,在同样的offset处,至少会有一份数据。
一致性问题
在讨论一致性问题前,先看看什么是consistency和defined
根据上面的图片,上面几个概念就很清晰了。
- consistent: 是指多个副本中的相应chunk都相同
- inconsistent: 多个副本中的相应chunk不尽相同
- defined: 比consistent严格,对于并发的写入,如果写入的数据大小超过一个chunk,那么不同client的chunk之间就会存在交叉的情况,则为undefined。见consistent图示,红蓝相间即为不同client的chunk交叉
下表即为GFS在不同情况下修改文件后的状态:
可以说,GFS这种弱一致性模型是针对其特殊应用场景的,可以获得很高的读写性能。