说明
本系列文章是对大名鼎鼎的 MIT6.824分布式系统课程 的翻译补充和学习总结,算是自己一边学习一边记录了。
如有疏漏错误,还请指正:)
持续更新ing。。。
翻译&补充
论文
The Google File System
Sanjay Ghemawat, Howard Gobioff, and Shun-Tak Leung
SOSP 2003
为什么我们需要读这篇论文?
分布式存储是很重要的概念
- 接口/语义 应该是什么样子的?
- 内部是如何工作的?
GFS论文覆盖了6.824中的很多主题:并行,容错,复制,一致性
良好的系统论文——细节从应用一直到网络都覆盖到
成功的实际应用的设计
为什么分布式存储很难?
高性能 --> 多台机器间数据分片
多台服务器 --> 经常出错
容错 --> 复制
复制 --> 不一致
更好地一致性 --> 低性能
对于一致性,应该怎么处理?
理想的模型:和一台服务器一样的行为表现
服务器使用硬盘存储
服务器在同一时刻只执行一条客户的操作(即便是并发的)
读之前所写,即便服务器崩溃或重启
因此:假设C1和C2并发地写,等到写操作完毕,C3和C4读。它们会获得什么?
C1: Wx1
C2: Wx2
C3: ---- Rx?
C4: -------- Rx?
回答:1或者2,但是C3和C4会看到相同的值。
这是一个“强”一致性的模型。
但是一台单独的服务器容错性很差。
为了容错的复制,很难实现强一致性
一个简单,但有问题的复制方案:
- 两个复制的服务器,S1和S2
- 多个客户端向两台服务器,并行发送写请求
- 多个客户端向其中一台,发送读请求
在我们的示例中,C1和C2的写请求可能会以不同的顺序到达两台服务器
- 如果C3从S1读取,可能会看到x=1
- 如果C4从S2读取,可能会看到x=2
或者如果S1接受了一个读请求,但是在发送写请求到S2时,客户端崩溃了,会怎么样?
这不是强一致性!
更好的一致性通常需要通信,来保证复制集的一致 —— 会很慢!
性能和一致性之间需要权衡很多,以后会看到
GFS
内容:
很多谷歌的服务需要大型快速的统一文件存储系统,比如:Mapreduce,爬虫/索引,日志存储/分析,Youtube(?)
全局来看(对于一个单独的数据中心):任何一个客户端可以读取任意文件,允许多个应用之间共享数据
在多个服务器/硬盘上自动化“切片”每个文件,提升并行的性能,增加空间可用度
错误的自动恢复
每次部署只有一个数据中心
只有谷歌的应用和用户
旨在大文件的的顺序操作;读或者追加。不是存储小数据的低延迟DB
在2003年有什么创新点?他们是怎么被SOSP接受?
不是分布式、分区、容错这些基本的思想
大规模
在工业界的实际应用经验
弱一致性的成功案例
单独master的成功案例
架构总览
客户端(库,RPC —— 但不像Unix文件系统那样可见)
每个文件切分为独立的64MB的数据块
数据块服务器,每个数据块复制3份
每个文件的数据块们分布在多个数据块服务器上,用于并行读写(比如,MapReduce),并且允许大文件只有一个master(!),master也会复制
工作的划分:master负责写名称,数据块服务器负责写数据
Master的状态
在RAM中(速度,应该是有点小的):
在硬盘上:
- 日志
- 检查点
为什么有日志和检查点?
为什么是大的数据块?
当客户端C想要读数据,是什么步骤?
- C发送文件名和偏移量到master M(如果没有缓存的话)
- M找到这个偏移量的数据块handle
- M回复最新版本的数据块服务器的列表
- C缓存handle和数据块服务器列表
- C发送请求到最近的数据块服务器,包括数据块handle和偏移量
- 数据块服务器从硬盘上读取数据块文件,并返回
master怎么知道数据块服务器含有一个指定的数据块?
当C想要在记录后追加,是什么步骤?
论文的图2
- C询问M文件的最后一个数据块
- 如果M发现数据块没有主记录(或者租约过期)
2a. 如果没有写数据块服务器的最新版本,错误
2b. 从最新的版本中选择主节点和备份节点
2c. 版本号增加,写到硬盘的日志上
2d. 告诉主记录和备份的记录他们是谁,以及新版本
2e. 在硬盘上复制地写入新版本 - M告诉C主记录和备份记录
- C向全部发送数据(只是暂时的。。。),并等待
- C告诉P需要追加
- P检查租约是否过期,数据块是否有空间
- P确定偏移量(数据块的结束)
- P写数据块文件(一个Linux文件)
- P告诉所有备份节点偏移量,告诉它们需要追加到数据块文件
- P等待所有备份节点的回复,超时则为错误,例如:硬盘空间不足
- P告诉C ok或错误
- 如果出错,C从头重试
GFS提供给客户端的是什么样的一致性保证
需要告诉应用以某种形式使用GFS。
这是一种可能性:
如果主节点告诉客户端一条记录成功追加,则所有的读者随后打开这个文件,都可以看到追加的记录。
(但是并非失败的追加就不可见,或者说,所有的读者都会看到相同的文件内容,相同顺序的记录)
我们怎么知道GFS是否完成了这些保证?
看它对不同种错误的处理方式:崩溃,崩溃+重启,崩溃+替代,信息丢失,分区。
请想一想GFS是怎么保证关键特性的。
* 一个追加的客户端在不合适的时刻失败了,怎么办?
有没有不合适的时刻存在?
* 一个追加客户端缓存了一个过期的(错误的)主节点,怎么办?
* 一个读的客户端缓存了一个过期的备份节点列表,怎么办?
* 一个主节点崩溃+重启,会导致文件的丢失吗?
或者忘记哪些数据块服务器存储指定的数据块?
* 两个客户端在同一时间进行记录追加。
他们会覆盖彼此的记录吗?
* 主节点在向所有备份节点发送追加请求时,主节点崩溃,会怎么样?
如果一个备份节点没有看到追加请求,会被选为新的主节点吗?
* 数据块服务器S4存储旧的过期的数据块备份,是离线的。
主节点和其他存活的备份节点都崩溃。
S4复活(在主节点和备份节点之前)。
master会选择S4(包含过期数据块)作为主节点吗?
是选择含有过期数据的节点作为左节点合适,还是选择没有备份的节点?
* 如果备份节点总是写入失败,主节点应该怎么做?
比如,死机,硬盘空间不足,或硬盘故障。
主节点应该从备份节点列表中丢弃该节点吗?
然后向追加记录的客户端返回成功?
或者主节点一直发送请求,认为请求都失败,
给客户端的每个写入请求都返回失败?
* 如果主节点S1是活跃的,服务于客户端的请求,但是master和S1之间的网络不通?
“网络分区”。
master会选择一个新的主节点吗?
这时候会存在两个主节点吗?
如果追加请求发送给一个主节点,读请求发送给另一个,是否打破了一致性的保障呢?
“脑裂”
* 如果有一个分区的主节点在处理服务端的追加请求,但是它的租约到期了,master选择了一个新的主节点,这个新的主节点会有之前主节点处理的最新的数据吗?
* 如果master失败会怎么样?
替换后的master知道之前master的所有信息吗?
比如,每个数据块的版本号?主节点?租约过期时间?
* 谁判断master是否死机且需要被替换?
master的备份会ping master吗?如果没有回应则接替它?
* 如果整个环境断电了,会怎么样?
如果电力恢复,所有的机器会重启,会怎样?
* 假设master想要创建一个新的数据块备份。
可能因为备份太少了。
假如它是文件的最后一个数据块,正在被追加。
新的备份怎么保证没有错误追加?毕竟它还不是一个备份节点。
* 存不存在一个场景,会打破GFS的保证?
例如,追加成功,但是随后的读者没有看到这条记录。
所有master的备份永久地丢失状态信息(永久硬盘错误)。可能更早:结果会是没有回答,而不是错误的数据。“故障-停止”
某个数据块的所有数据块服务器丢失硬盘文件。又是,“故障-停止”;并不是最坏的结果
CPU,RAM,网络或硬盘出现一个错误值。校验和会检查出一些情况,但不是全部
时钟没有正确地同步,所以租约没有正常工作。所以,会存在多个主节点,可能写请求在一个节点上,读请求在另一个节点上。
GFS允许哪些应用的不规范行为?
所有的客户端都会看到一样的文件内容吗?会不会一个客户端可以看见一条记录,但是其他客户端看不见?一个客户端读取文件两次是看见相同的内容吗?
所有的客户端都可以看到相同顺序的追加记录吗?
这些不规范行为会为应用带来麻烦吗?
比如MapReduce?
怎么样才能没有异常 —— 强一致性?
例如,所有的客户端看到相同的文件内容。
很难给出一个真实的解答,不过有一些注意事项。
- 主节点应当检测重复的客户端写请求。或者客户端不应当发送这种请求。
- 所有的备份节点应该完成每个写操作,或者全部不完成。或者先暂定写入,直到所有节点确定再完成写入。只有所有节点同意完成才进行写入操作!
- 如果主节点崩溃,一些备份节点会错误最后一部分操作。新的主节点会和所有的备份节点通信,找出最近的所有操作,并同步给其余备份节点。
- 避免客户端从过期的前备份节点读取,或者所有的节点必须与主节点通信,或者所有的备份节点应当也有租约。
你们会在实验3和4看到这些内容!
性能(图表3)
读的大量聚合吞吐(3个复制集,拆开)
- 16个数据服务器,总共 94MB/s 或者每个数据块服务器 6MB/s,这样不错吧?一个硬盘的顺序吞吐量大约为 30MB/s,一个网卡的大约在 10MB/s
- 接近网络饱和(交换机链路)
- 所以:单独服务器的性能是低的,但是扩展性不错。那一个更重要?
- 表格3展示了GFS产品 500MB/s,是很高的
不同文件的写是比可能的最大值要低,作者认为是网络的影响(但是没有具体说明)
单个文件的并发追加,受限于存储最后一个数据块的服务器
15年后难以预料,例如,硬盘的速度有多快?
一些需要考虑的问题
怎么样能够良好地支持小文件?
怎么样能良好地支持千万级别的文件?
GFS可以成为广泛使用的文件系统吗?在不同的城市有备份?在同一个数据中心有多个备份,容错性不高!
GFS从错误恢复需要多久?一个主节点/备份节点的错误需要多久?master的错误呢?
GFS怎么应对缓慢的数据块服务器?
与GFS工程师的回顾性对话:
文件数目是最大的问题
- 最终的数目是图表2的1000倍
- 在master的内存中存储不下
- master垃圾回收时,扫描所有的文件和数据块,很慢
千级别的客户数量会给master的CPU带来很大的压力
应用需要以符合GFS语义和限制的方式进行设计
master的故障恢复最初是完全人工完成,需要10分钟左右
BigTable是多个小文件的解决方案,Colossus可以在多台master上分片master数据
总结
性能,容错,一致性的案例研究,为MapReduce应用定制
好的想法:
- 全局的文件集群系统作为一个基础设施
- 将命名(master)和存储(数据块服务器)分离
- 并行吞吐的分片
- 大的文件/数据块,降低开销
- 主节点用于顺序写
- 租约,为了防止数据块服务器的主节点脑裂
不足的地方:
单个master的性能,耗尽内存和CPU
数据块服务器对于小文件并不高效
master没有自动的故障切换
或许一致性还是比较弱
有疑问加站长微信联系(非本文作者)