本论文主要描述了 Google GFS 分布式文件系统的设计与实现。
论文地址:GFS (2003)
目录:
Google GFS 是一个面向大规模数据密集型应用的、可伸缩的分布式文件系统。
设计理念:
与传统的分布式文件系统相比:
- 相同之处:追求性能、可伸缩性、可靠性以及可用性。
- 不同之处:基于 Google 对自己的应用的负载情况和技术环境的观察。
设计假设:
- 组件失效被认为是常态事件,而不是意外事件。
- 由于 GFS 组件的数量较大,这导致在任何给定时间内都有组件可能发生故障。
- 以通常的标准衡量,文件体积非常巨大。
- 通常是 GB、TB 级别,故不适用于传统管理数亿个 KB 大小文件的方式。
- 绝大部分文件的修改是采用在文件尾部追加数据,而不是覆盖原有数据的方式。
- 大量的数据的符合这一特性(如:数据分析程序扫描的超大数据集、正在运行的程序生成的连续的数据流、存档的数据、程序的操作日志),通常一旦写完之后,仅对文件进行顺序读操作,因此更加关注数据的追加操作的性能优化和原子性保证。
- 应用程序和文件系统 API 的协同设计提高了整个系统的灵活性。
- 放松了对 GFS 一致性模型的要求,减轻了文件系统对应用程序的苛刻要求,大大简化了 GFS 的设计。
- 引入了原子性的记录追加操作,省略了额外的同步操作。
一个 GFS 集群包含:
- 一个单独的
Master
节点- 指逻辑上仅有一个
Master
节点,实际上出于高可用性会有多个Master
节点的复制。
- 指逻辑上仅有一个
- 多个
Chunk
服务器
并且同时被多个客户端访问。
GFS 存储的文件都被分割成固定大小的 Chunk
:
- 在
Chunk
创建的时候,Master
服务器会给每个Chunk
分配一个不变的、全球唯一的 64 位的Chunk
标识。 Chunk
服务器把Chunk
以 Linux 文件的形式保存在本地硬盘上,并且根据指定的Chunk
标识和字节范围来读写块数据。- 出于可靠性的考虑,每个块都会复制到多个块服务器上。缺省情况下,GFS 使用
3
个存储复制节点,不过用户可以为不同的文件命名空间设定不同的复制级别。
Chunk
尺寸:
单个 Chunk
的大小是 64 MB ,选择该尺寸的几个重要优点:
- 减少了客户端和
Master
节点通讯的需求;- 因为只需要和 Mater 节点的通信一次就可以获取
Chunk
的位置信息,之后就可以对同一个Chunk
进行多次的读写操作。而采用大尺寸的Chunk
可以使客户端轻松缓冲大量工作数据集所有的Chunk
位置信息。
- 因为只需要和 Mater 节点的通信一次就可以获取
- 客户端能够对一个块进行多次操作,这样就可以通过与
Chunk
服务器保持较长时间的 TCP 连接来减少网络负载; - 减少了
Master
节点需要保存的元数据的数量。这就允许我们把元数据全部放在内存中。
Master
节点管理所有的文件系统元数据。这些元数据包括 namespace、访问控制信息、文件和Chunk
的映射信息、以及当前Chunk
的位置信息。Master
节点还管理着系统范围内的活动。比如,Chunk
租约管理、孤儿Chunk
的回收、以及Chunk
在Chunk
服务器之间的迁移。
Master
节点使用心跳信息周期地和每个 Chunk
服务器通讯,发送指令到各个 Chunk
服务器并接收 Chunk
服务器的状态信息。
客户端和 Master
节点的通信只获取元数据,客户端将这些元数据信息缓存一段时间,后续将直接与 Chunk
服务器进行数据读写操作。
无论是客户端还是 Chunk
服务器都不需要缓存文件数据,因为:
- 客户端:通常读取的文件较大无法被缓存,仅会缓存元数据;
Chunk
服务器:Chunk
以本地文件的方式保存,Linux 操作系统的文件系统缓存会把经常访问的数据缓存在内存中。
读取流程:
- 客户端把文件名和程序指定的字节偏移,根据固定的
Chunk
大小,转换成文件的Chunk
索引(size / 64 MB)。 - 客户端把文件名和
Chunk
索引发送给Master
节点。Master
节点将相应的Chunk
标识和副本的位置信息发还给客户端。客户端用文件名和Chunk
索引作为 key 缓存这些信息。 - 客户端发送请求到其中的一个副本处,一般会选择最近的。请求信息包含了
Chunk
的标识和字节范围。- 在对这个
Chunk
的后续读取操作中,客户端不必再和Master
节点通讯了,除非缓存的元数据信息过期或者文件被重新打开。 - 实际上,客户端通常会在一次请求中查询多个
Chunk
信息,Master
节点的回应也可能包含了紧跟着这些被请求的Chunk
后面的Chunk
的信息。在实际应用中,这些额外的信息可以避免了客户端和Master
节点未来可能会发生的几次通讯。
- 在对这个
Master
服务器主要存储 3 种类型的元数据,包括:
- 文件和
Chunk
的命名空间; - 文件和
Chunk
的映射关系; - 每个
Chunk
副本的存放地点。
所有的元数据都保存在内存中,前两种类型的元数据会以记录变更日志的方式记录在操作系统的系统日志文件中,日志文件存储在本地磁盘上,同时也会被复制到远程 Master
节点上。
Master
服务器不会持久保存 Chunk
位置信息。Master
服务器在启动时,或者有新的 Chunk
服务器加入时,向各个 Chunk
服务器轮询它们所存储的 Chunk
的信息。
因为元数据保存在内存中,所以 Master
服务器的操作速度非常快。并且,Master
服务器可以在后台简单而高效的周期性扫描自己保存的全部状态信息。
潜在问题:Chunk
的数量以及整个系统的承载能力都受限于的数量以及整个系统的承载能力都受限于 Master
服务器所拥有的内存大小。
Master
服务器并不保存持久化保存哪个 Chunk
服务器存有指定 Chunk
的副本的信息。Master
服务器只是在启动的时候轮询 Chunk
服务器以获取这些信息。Master
服务器能够保证它持有的信息始终是最新的,
这种设计的优点:这种设计简化了在有 Chunk
服务器加入集群、离
开集群、更名、失效、以及重启的时候, Master
服务器和 Chunk
服务器数据同步的问题。在一个拥有数百台
操作日志包含了关键的元数据变更历史记录。
GFS 会把日志复制到多台远程机器,并且只有把相应的日志记录写入到本地以及远程机器的硬盘后,才会响应客户端的操作请求。Master
服务器会收集多个日志记录后批量处理,以减少写入磁盘和复制对系统整体性能的影响。
Master
服务器在灾难恢复时,通过重演操作日志把文件系统恢复到最近的状态。
Master
服务器在日志增长到一定量时对系统状态做一次 Checkpoint
GFS 设计的重要原则:最小化 Master
节点在所有操作中的参与程度。
GFS 使用租约机制来保证多个 Chunk
副本之间变更顺序的一致性。
Master
节点会选择一个 Chunk
服务器建立租约,将其作为 primary Chunk
,primary Chunk
会对所有更改操作进行序列化,并且其他所有副本都将遵从这个序列。
租约机制的目的是最小化 Master
节点的管理负担。
为了提高网络效率,我们采取了把数据流和控制流分开的措施。
为了充分利用每台机器的带宽,数据沿着一个 Chunk
服务器链顺序的推送,而不是以其它拓扑形式分散推送(例如,树型拓扑结构)。线性推送模式下,每台机器所有的出口带宽都用于以最快的速度传输数据。
GFS 提供了一种原子的数据追加操作 记录追加。
果记录追加操作在任何一个副本上失败了,客户端就需要重新进行操作。重新进行记录追加的结果是,同一个Chunk
的不同副本可能包含不同的数据–重复包含一个记录全部或者部分的数据。GFS并不保证Chunk
的所有副本在字节级别是完全一致的。它只保证数据作为一个整体原子的被至少写入一次。
我们用标准的 copy-on-write 技术实现快照。当 Master
节点收到一个快照请求,它首先取消作快照的文件的所有 Chunk
的租约。这个措施 保证了后续对这些 Chunk
的写操作都必须与 Master
交互以找到租约持有者。这就给 Master
节点一个率先创建 Chunk
的新拷贝的机会。
GFS 使用 快速恢复 和 复制 这两大策略来保证整个系统的高可用性。
Master
和 Chunk
服务器都被设计为可以在数秒内恢复它们的状态并重新启动。
每个 Chunk
都被复制到不同机架上的不同 Chunk
服务器上,用户可以为文件命名空间的不同部分设定不同的复制级别。缺省是 3(即副本数量为 3)。当有 Chunk
服务器离线了,或者通过 Checksum 校验发现了已经损坏的数据, Master
节点通过克隆已有的副本保证每个 Chunk
维持设定的副本数量。
为了保证 Master
服务器的可靠性, Master
服务器的状态也要复制 Master
服务器所有的操作日志和 checkpoint 文件都被复制到多台机器上。
文件都被复制到多台机器上。对 Master
服务器状态的修改操作能够提交成的前提是,操作日志写入到 Master
服务器的备节点和本机的磁盘。简单说来,一个
此外,此外,GFS中还有些“影子”中还有些“影子服务器,这些“影子”服务器在“主”服务器,这些“影子”服务器在“主”Master
服务器宕机的时候提,GFSGFS”Master``Master
”供文件系统的只读访问。
“影子”Master
服务器为了保持自身状态是最新的,它会读取一份当前正在进行的操作的日志副本,并且依照和主 Master
服务器完全相同的顺序来更改内部的数据结构。
每个 Chunk
服务器都使用 Checksum 服务器都使用来检查保存的数据是否损坏。
。如果发生某个块的不正确,服务器返回给请求者一个错误信息,并且通知服务器这个错误。作为回应,服务器这个错误。作为回应,Checksum不正确,不正确,Chunk``Chunk``Master
请求者应当从其它副本读取数据服务器也会从其它副本克隆数据进行恢复。当一个新的副本就绪后,,Master``Master
服务器通知副本错误的服务器删掉错误的副本。服务器删掉错误的副本。Master``Chunk
通过详细而深入的诊断日志,来帮助诊断问题、调试、以及性能分析。