GFS系统架构
针对上述观察,我们发现它们与早期文件系统的设计假设存在显著差异。为此,我们采取了以下解决方案:
- 组件故障:我们接受故障为常态,系统设计以自我监控和快速恢复为原则,适应低成本硬件环境下的持续运行。
- 文件规模:主要是文件大小超100MB。小文件兼容,不做优先。
- 数据修改:倾向于追加而非覆盖,优化大规模顺序写入,随机写入仅有效支持。
- API协同设计:应用程序与文件系统API的深度整合,提升了系统灵活性。我们重视持续高带宽,满足大规模数据处理需求,而非单一操作的低延迟。优先支持高吞吐优而非低延时。
GFS采用了一个Master
节点和多个chunkserver
节点的构成,Master
节点负责维护整个文件系统的元数据,而实际的文件数据则以chunk
为单位(块的大小固定不变,64字节)分散存储在各个chunkserver
节点上(默认情况下,我们存储3个副本)。每个chunk
都拥有一个独一无二的句柄(handle
),这使得它们能够被Master
节点准确识别。
The master maintains all file system metadata. This includes the namespace, access control information, the mapping from files to chunks, and the current locations of chunks. It also controls system-wide activities such as chunk lease management, garbage collection of orphaned chunks, and chunk migration between chunkservers. The master periodically communicates with each chunkserver in HeartBeat messages to give it instructions and collect its state.
Master
节点负责维护所有的文件系统元数据,包括命名空间、访问控制信息、文件到数据块的映射以及数据块的当前存储位置。此外,它还控制系统级别的活动,如数据块租约管理、孤立数据块的垃圾回收和数据块在服务器之间的迁移。主节点会定期通过心跳消息与每个数据块服务器通信,以下达指令并收集状态信息。
客户端与文件数据的交互并不是直接通过Master
节点进行的。相反,它采取了一种更为智能和间接的方式:客户端首先向Master
节点发起询问,以获取需要联系的chunkserver
节点信息。Master
节点根据当前的文件系统状态和chunk
分布情况,向客户端指明哪些chunkserver
节点持有所需的数据块。
GFS
的读取操作流程极为简洁:
-
客户端请求:客户端向
Master
节点发送请求,提供所需文件的名称和数据的偏移量。 -
Master响应:
Master
节点根据请求,回复客户端chunk
的句柄和包含目标chunk
的chunkserver
地址列表。客户端将这一结果缓存,以备后续使用。 -
客户端发起读取:客户端根据
Master
提供的信息,选择最近的chunkserver
发起读取请求。 -
chunkserver响应:被请求的
chunkserver
将请求的数据发送回客户端。
GFS
的chunk size
设定为64MB
,这一尺寸显著超越了传统文件系统的block size
。这种设计选择带来了以下益处:首先,它减少了客户端与Master节点交互的需要。其次,它可以降低网络开销。第三,它减少了存储在Master节点上的元数据大小。
- First, it reduces clients’ need to interact with the master.
- Second, it can reduce network overhead.
- Third, it reduces the size of the metadata stored on the master.
Master
节点负责维护三种关键类型的元数据,它们构成了GFS架构的核心:
- 文件和块的命名空间:
Master
节点存储了文件系统的命名空间信息,这包括所有文件和目录的层次结构和名称。 - 文件到块的映射:
Master
节点管理着从文件到存储块的映射关系,确保每个文件的数据能够被准确地定位到对应的chunk
。 - 块副本的位置信息:
Master
节点还记录了每个chunk
的副本位置信息,这涉及到数据的冗余存储和分布式部署,以确保数据的高可用性和容错性。
The first two types (namespaces and file-to-chunk mapping) are also kept persistent by logging mutations to an operation log stored on the master’s local disk and replicated on remote machines.
在GFS
中,命名空间和文件到chunk
的映射这两种元数据是至关重要的,它们会被持久化存储到磁盘。任何对这些元数据的修改都会被详细记录在操作日志中,确保了数据变更的持久性和可审计性。
与此相反,chunk
副本的位置信息则不会持久化存储。当Master
节点启动或有新的chunkserver
节点加入集群时,Master
节点会主动与chunkserver
节点通信,动态获取这些信息。
Master
节点通过定期与chunkserver
节点的心跳检测来获取chunk
的位置信息,而不是将这些信息持久化存储。这种设计选择背后的原因是:
A chunkserver has the final word over what chunks it does or does not have on its own disks.
-
复杂性管理:如果选择持久化
chunk
位置信息,Master
节点就需要不断同步与chunkserver
节点之间的数据,以保持一致性。这在chunkserver
节点频繁进行扩缩容、故障转移(failover)、重命名等操作时,会变得相当复杂。 -
权威性来源:
chunkserver
节点直接管理着存储在本地的chunk
,因此它们拥有关于chunk
位置和状态的最终话语权。例如,在chunk
损坏或出现其他问题时,只有chunkserver
节点能够提供最准确和及时的信息。
Not only is it the only persistent record of metadata, but it also serves as a logical timeline that defines the order of concurrent operations.
operation log
不仅元数据的唯一持久记录,还充当了一个逻辑时钟,为系统内发生的事件提供了一个统一的时间戳序。
-
一致性:当一个文件区域被修改后,如果所有客户端无论访问哪个副本(
replica
)都能看到相同的状态,这个区域就被认为是一致的。 -
确定性:如果客户端不仅能看到一致的状态,还知道修改后的具体内容,那么这个状态就被称为确定的。
GFS has a relaxed consistency model that supports our highly distributed applications well but remains relatively simple and efficient to implement.
GFS
对于一致性实现比较宽松,GFS
通过以下机制确保文件区域在多次成功修改后保持确定性:
-
修改顺序:所有副本按照相同的顺序应用修改,确保了全局的一致性。
-
版本控制:使用
chunk
版本号来识别哪些副本已经过时,这些过时的副本将不会参与后续的读写操作,并最终被垃圾回收机制清除。
尽管存在一个小的时间窗口,客户端的缓存可能使其读取到过时的数据,但这种情况很少发生,因为:
-
缓存更新:客户端通常会在缓存过期前与
Master
节点通信,以获取最新的chunk
位置信息。 -
副本恢复:
Master
节点会在副本损坏或过时后迅速恢复新的副本,除非在极短的时间内所有副本都损坏了。即使在这种情况下,数据也只是丢失而不是被错误地写入,应用程序可以接收到确定的异常信号,而不是错误的数据。
本章节详细描述了GFS的架构,包括主服务器和块服务器如何协同工作以及元数据管理。