Google三大论文之GFS
Google GFS(Google File System) 文件系统,一个面向大规模数据密集型应用的、可伸缩的分布式文件系统。GFS 虽然运行在廉价的普遍硬件设备上,但是它依然了提供灾难冗余的能力,为大量客户机提供了高性能的服务。
1 简介
GFS 与传统的分布式文件系统有着很多相同的**设计目标,比如,性能、可伸缩性、可靠性以及可用性。**设计需要考虑的问题:
- 1. 组件失效被认为是常态事件,而不是意外事件。GFS 包括几百甚至几千台普通的廉价设备组装的存储机器,同时被相当数量的客户机访问。GFS 组件的数量和质量导致在事实上,任何给定时间内都有可能发生某些组件无法工作,某些组件无法从它们目前的失效状态中恢复。比如应用程序 bug、操作系统的 bug、人为失误,甚至还有硬盘、内存、连接器、网络以及电源失效等造成的问题。所以,持续的监控、错误侦测、灾难冗余以及自动恢复的机制必须集成在 GFS 中。
- 2. 其次,以通常的标准衡量,文件非常巨大。数 GB 的文件非常普遍,每个文件通常都包含许多应用程序对象。设计的假设条件和参数,比如 I/O 操作和 Block 的尺寸都需要重新考虑。
- 3. 绝大部分文件的修改是采用在文件尾部追加数据,而不是覆盖原有数据的方式。对文件的随机写入操作在实际中几乎不存在。一旦写完之后,对文件的操作就只有读,而且通常是按顺序读。对于这种针对海量文件的访问模式,客户端对数据块缓存是没有意义的,数据的追加操作是性能优化和原子性保证的主要考量因素。
- 4. 应用程序和文件系统 API 的协同设计提高了整个系统的灵活性。对 GFS 一致性模型的要求,这样就减轻了文件系统对应用程序的苛刻要求,大大简化了 GFS 的设计。引入了原子性的记录追加操作,从而保证多个客户端能够同时进行追加操作,不需要额外的同步操作来保证数据的一致性。
2 设计概述
2.1 设计预期
系统由许多廉价的普通组件组成,组件失效是一种常态。系统必须持续监控自身的状态,它必须将组件失效作为一种常态,能够迅速地侦测、冗余并恢复失效的组件。
系统的工作负载主要由两种读操作组成:大 规模的流式读取和小规模的随机读取。小规模的随机读取通常是在文件某个随机的位置读取几个 KB 数据。如果应用程序对性能非常关注,通常的做法是把小规模的随机读取操作合并并排序,之后按顺序批量读取,这样就避免了在文件中前后来回的移动读取位置。数据一旦被写入后,文件就很少会被修改了。系统必须高效的、行为定义明确的2实现多客户端并行追加数据到同一个文件里的语意。文件被用于“生产者-消费者”队列,或者其它多路文件合并操作。最小的同步开销来实现的原子的多路追加数据操作是必不可少的。
2.2 接口
GFS 提供了一套类似传统文件系统的 API 接口函数,文件以分层目录的形式组织,用路径名来标识。支持常用的操作,如创建新文件、删除文件、打开文件、关闭文件、读和写文件。
2.3 架构
一个 GFS 集群包含一个单独的 Master 节点3、多台 Chunk 服务器,并且同时被多个客户端访问,
GFS 存储的文件都被分割成固定大小的 Chunk。在 Chunk 创建的时候,Master 服务器会给每个 Chunk 分配一个不变的、全球唯一的 64 位的 Chunk 标识。Chunk 以 Linux 文件的形式保存在本地硬盘上,并且根据指定的 Chunk 标识和字节范围来读写块数据。
Master 节点管理所有的文件系统元数据。Chunk 租用管理、孤儿 Chunk的回收、以及 Chunk 在 Chunk 服务器之间的迁移。Master 节点使用心跳信息周期地和每个 Chunk服务器通讯,发送指令到各个 Chunk 服务器并接收 Chunk 服务器的状态信息。客户端缓存数据几乎没有什么用处,因为大部分程序要么以流的方式读取一个巨大文件,要么工作集太大根本无法被缓存。
2.4 单一 Master 节点
单一的 Master 节点可以通过全局的信息精确定位Chunk 的位置以及进行复制决策。必须减少对 Master 节点的读写,避免 Master 节点成为系统的瓶颈。客户端并不通过 Master 节点读写文件数据。首先,客户端把文件名和程序指定的字节偏移,根据固定的 Chunk 大小,转换成文件的Chunk 索引。然后,它把文件名和 Chunk 索引发送给 Master 节点。Master 节点将相应的 Chunk 标识和副本的位置信息发还给客户端。客户端用文件名和 Chunk 索引作为 key 缓存这些信息。客户端通常会在一次请求中查询多个 Chunk 信息,Master 节点的回应也可能包含了紧跟着这些被请求的 Chunk 后面的 Chunk 的信息。
2.5 Chunk 尺寸
Chunk 的大小是关键的设计参数之一,选择了 64MB。每个 Chunk 的副本都以普通 Linux 文件的形式保存在 Chunk 服务器上,只有在需要的时候才扩大。惰性空间分配策略避免了因内部碎片造成的空间浪费,内部碎片或许是对选 择这么大的 Chunk 尺寸最具争议一点。
选择较大的 Chunk 尺寸有几个重要的优点:
- 减少了客户端和 Master 节点通讯的需求,因为只需要一次和 Mater 节点的通信就可以获取 Chunk 的位置信息,之后就可以对同一个 Chunk 进行多次的读写操作
- 采用较大的 Chunk 尺寸,客户端能够对一个块进行多次操作,这样就可以通过与 Chunk 服务器保持较长时间的 TCP 连接来减少网络负载
- 选用较大的 Chunk 尺寸减少了 Master节点需要保存的元数据的数量
采用较大的 Chunk 尺寸也有其缺陷:
- 当有许多的客户端对同一个小文件进行多次的访问时,存储这些 Chunk 的 Chunk 服务器就会变成热点
- 一个可执行文件在GFS 上保存为 single-chunk 文件,之后这个可执行文件在数百台机器上同时启动
- 几个 Chunk 服务器被数百个客户端的并发请求访问导致系统局部过载
- 通过使用更大的复制参数来保存可执行文件,以及错开批处理队列系统程序的启动时间的方法解决了这个问题
- 长效解决方案是允许客户端从其它客户端读取数据
2.6 元数据
Master 服务器存储 3 种主要类型的元数据,所有的元数据都保存在 Master 服务器的内存中。包括:
- 文件和 Chunk 的命名空间
- 文件和 Chunk 的对应关系
- 每个 Chunk 副本的存放地点