MIT6.824分布式系统课程 翻译&学习笔记(三)GFS

raesnow · · 1559 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

说明

本系列文章是对大名鼎鼎的 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中(速度,应该是有点小的):
image.png
在硬盘上:

  • 日志
  • 检查点
为什么有日志和检查点?
为什么是大的数据块?
当客户端C想要读数据,是什么步骤?
  1. C发送文件名和偏移量到master M(如果没有缓存的话)
  2. M找到这个偏移量的数据块handle
  3. M回复最新版本的数据块服务器的列表
  4. C缓存handle和数据块服务器列表
  5. C发送请求到最近的数据块服务器,包括数据块handle和偏移量
  6. 数据块服务器从硬盘上读取数据块文件,并返回
master怎么知道数据块服务器含有一个指定的数据块?
当C想要在记录后追加,是什么步骤?

论文的图2

  1. C询问M文件的最后一个数据块
  2. 如果M发现数据块没有主记录(或者租约过期)
    2a. 如果没有写数据块服务器的最新版本,错误
    2b. 从最新的版本中选择主节点和备份节点
    2c. 版本号增加,写到硬盘的日志上
    2d. 告诉主记录和备份的记录他们是谁,以及新版本
    2e. 在硬盘上复制地写入新版本
  3. M告诉C主记录和备份记录
  4. C向全部发送数据(只是暂时的。。。),并等待
  5. C告诉P需要追加
  6. P检查租约是否过期,数据块是否有空间
  7. P确定偏移量(数据块的结束)
  8. P写数据块文件(一个Linux文件)
  9. P告诉所有备份节点偏移量,告诉它们需要追加到数据块文件
  10. P等待所有备份节点的回复,超时则为错误,例如:硬盘空间不足
  11. P告诉C ok或错误
  12. 如果出错,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没有自动的故障切换
或许一致性还是比较弱


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:raesnow

查看原文:MIT6.824分布式系统课程 翻译&学习笔记(三)GFS

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1559 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传