悦读:关于GFS的22个[较]重要问题(更新中)

悦读:关于GFS的22个[较]重要问题(更新中)

序言

"The Google File System" 应该是很多人阅读的第一篇分布式系统领域的论文,它提供了诸多全新的思路来解决Google当时面临的大数据存储方面的问题,对于接下来数十年的分布式系统领域的快速发展起到了奠基式的作用。

相信很多人和我一样,即使阅读这篇论文很多遍,依然对论文中的各种设计思路、实现细节,特别是对于方法背后的权衡充满疑问。

本篇博客试着换一种记录阅读论文笔记的方式,不再复述和总结论文中的内容,而是在阅读论文之后,提出一些或重要或不重要的问题,进一步尝试回答这些问题。

说明:
1. 本篇博客适合在精度论文之后来阅读。
2. 以下这些问题是我在阅读论文的过程中觉得值得思考和讨论的,如果大家觉得还有哪些有趣的问题,也可以在留言中反馈,我一并整理在下面。

问题们

  1. GFS对于分布式文件系统的应用场景所做的假设和之前的各种分布式存储系统有何不同?这种不同的假设又带来了哪些关键的设计选择?
  2. GFS对外提供哪些接口?
  3. Master节点都维护哪些系统元数据?
  4. 为什么不论是客户端还是ChunkServer端,均不实现文件的读缓存?
  5. 为什么要减少Master节点在读写流程中的参与程度?如何减少?
  6. GFS为什么选择大的ChunkSize(64M)?有什么好处?有什么坏处?
  7. 为什么不在Master节点上持久化Chunk位置信息,而是每个ChunkServer启动时向Master节点汇报?
  8. 如何提高Master节点的故障恢复速度?
  9. Master节点如何做Checkpoint?
  10. GFS的一致性模型是怎么样的?GFS的一致性模型对于应用程序来说意味着什么?
  11. 什么是GFS的一致性模型里所说的Consistent?什么是Defined?什么时候会出现 “consistent but undefined” 的情况?
  12. 为什么会出现Stale的Chunk?如何解决这种Stale的Chunk?
  13. GFS为什么要引入租约(Lease)机制?
  14. GFS为什么要将数据流和控制流分离?
  15. GFS的多个副本之间是字节一致的吗?
  16. Master节点如何对元数据操作进行并发控制?为什么Master节点支持多个客户端并发在同一个目录下创建文件?
  17. GFS在什么时候会创建一个新的Chunk Replica?为新的Chunk Replica选择创建位置的时候会考虑哪些因素?
  18. 集群扩容新增了存储节点时,在为Chunk Replica选择位置时需要注意什么?
  19. 基于垃圾回收的数据删除有哪些优点?
  20. GFS通过哪些机制保证数据的完整性?
  21. GFS如何做Snapshot?
  22. 从CAP的角度来看,GFS是如何进行取舍的?

回答

问题1. GFS对于分布式文件系统的应用场景所做的假设和之前的各种分布式存储系统有何不同?这种不同的假设又带来了哪些关键的设计选择?

假设:
1. 系统的组件出现故障是常态,而非偶然。论文中甚至说在任一时刻“保证”有组件处于故障状态:“The quantity and quality of the components virtually guarantee that some are not functional at any given time and some will not recover from their current failures”,用Werner Vogels的话讲就是:“Everything fails, all the time”;
2. 存储在系统中的文件相对都很大:“typically 100 MB or larger in size, Multi-GB files are the common case”。正因为这个假设,GFS才可以采用64M的ChunkSize,才可以将所有的元数据都放在Master节点的内存中;
3. 文件的访问模式是:追加写、顺序读、随机读、不更新,随机写操作极少。因此文件系统优化的主要目标是提高追加写的性能(包括支持多个客户端的并发追加操作),同时没有必要在客户端实现读缓存;说明:多个客户端并发写文件这种访问模式应该大量存在于当时Google的应用场景中,因此GFS特别强调了要优化客户端的并发写操作
4. 整个系统的大吞吐量比更低的响应延迟更重要;

设计选择(列举部分):
1. 在系统设计中要充分考虑持续监控、错误检测、故障容忍、自动恢复等非功能性需求,并将对这些问题的考虑内化到系统设计中;
2. 可以将所有的文件系统元数据都放在Master节点的内存中;
3. 定义了更简单但更加适合业务场景的文件系统接口,针对业务场景来优化;
4. ……

问题2. GFS对外提供哪些接口?

GFS虽是一个文件系统,但并没有遵循标准的POSIX接口,而仅仅提供了一下接口:
1. Create 创建文件(仅元数据操作)
2. Delete 删除文件(延迟删除与垃圾回收)
3. Open 打开文件
4. Close 关闭文件
5. Read 读文件
6. Write 写文件
7. Record Append 原子性追加写操作(GFS重点优化的操作)
8. Snapshot 对文件或目录做快照

问题3. Master节点都维护哪些系统元数据?

Master节点维护的最核心的三层元数据结构:
第一层,文件系统的逻辑元数据(包括层级目录结构以及访问控制等)
第二层,文件同Chunk之间的关系(相当于逻辑和物理的中间层)
第三层,每个Chunk所在的具体位置的信息(几个副本,在哪些ChunkServer上)

同时,Master节点还维护了租约信息、Chunk版本号信息、副本状态迁移信息、垃圾回收信息等;

需要说明的是,尽管Master维护了整个文件系统的元数据信息,但是GFS通过减少Master节点在文件读写时的参与度,大大降低了Master节点的负担。这些会在其他的问题中回答。

问题4. 为什么不论是客户端还是ChunkServer端,均不实现文件的读缓存?

这里所说的读缓存,指的是文件内容的缓存。实际上,客户端会缓存文件系统的元数据(File, Chunk, ChunkServer的映射关系)来降低文件读写过程中同Master节点的交互。

客户端不缓存文件内容的原因是:
1. 应用通常都是顺序读(而不是同一个文件区域的随机读),因此缓存意义不大(预读倒是有意义的)
2. 应用程序要读的数据量通常很大,缓存不下
3. 客户端不缓存可以简化客户端操作,不用处理缓存一致性等麻烦问题

ChunkServer端不缓存的原因是:
1. ChunkServer端的内核文件系统会做缓存
2. 其实做缓存意义也不大
编辑于 2018-11-01