0%

GFS

Google GFS:分布式文件系统的开山之作,HDFS 就是照着它做的

Google 的数据量到了 PB 级,单机文件系统撑不住了——硬盘不够大、数据没备份、节点会坏。

GFS 就是 Google 为这个场景设计的分布式文件系统。它不追求 POSIX 兼容,不追求低延迟,追求的是:海量数据、高吞吐、容错性强、能跑在普通硬件上。

后来 Hadoop 的 HDFS 就是 GFS 的开源实现——架构一样、概念一样、连组件名字都是对应的。

GFS 的三个角色:各管一摊

GFS 是典型的主从架构,三个角色分工明确:

graph TD
    A[客户端 Client
应用程序接口] -->|1. 获取元数据| B[主控服务器 Master
元数据管理] A -->|2. 直接读写数据| C[数据块服务器 ChunkServer1] & D[ChunkServer2] & E[ChunkServer3] B -->|3. 心跳/元数据同步| C & D & E C & D & E -->|存储数据| F[本地磁盘
Chunk 副本] note[核心思想 Master 管元数据,ChunkServer 存数据,Client 直接访问数据节点]
角色 管什么 存什么
Master 管”账本”:文件名、目录、Chunk 位置 元数据(全在内存里)
ChunkServer 管”货”:实际数据块 Chunk 数据(本地磁盘)
Client 应用程序接口 缓存元数据,不存数据

关键设计:Master 不参与数据读写。 Client 只找 Master 要”数据在哪”,拿到地址后直接跟 ChunkServer 传数据。Master 不经过数据流,压力小,集群规模可以做得很大。

Chunk:64MB 的大数据块

GFS 把文件切成固定大小的 Chunk(数据块),默认 64MB。

为什么是 64MB?不是 4KB?

设计考量 说明
减少元数据量 一个文件需要的 Chunk 数量少,Master 内存能装下更多元数据
减少网络请求 Client 一次性拿到的 Chunk 位置信息覆盖范围大
适合大数据场景 连续读写 64MB,比频繁寻道效率高得多
简化副本管理 大块复制比小块复制更高效

注意:64MB 是 GFS 的默认值,HDFS 后来改成了 128MB。 磁盘越来越快,块大小也跟着涨。

副本机制:默认 3 份,节点挂了自动补

每个 Chunk 默认存 3 份副本,分布在不同的 ChunkServer 上。

  • 一个节点坏了 → 其他节点还有副本
  • 一个机架断电了 → 其他机架还有副本

Master 的职责:

  • 监控副本数量,发现少了就自动复制补足
  • 把新副本分配到负载低的节点
  • 定期扫描,回收被删除文件的 Chunk

租约机制:写一致性怎么保证?

GFS 最常见的写操作是追加(Append)——不是覆盖,是在文件末尾加数据。

并发追加的问题是:多个 Client 同时写同一个 Chunk,谁先谁后?怎么保证所有副本写的内容一致?

GFS 的解法是”租约”:

  1. Master 给每个 Chunk 指定一个 主 ChunkServer(Primary),授予租约(默认 60 秒有效)
  2. 所有写操作由 Primary 协调:
    • Client 把数据发给所有副本(Primary + Secondary)
    • Client 问 Primary “可以写了吗?”
    • Primary 确定写入顺序,通知所有 Secondary 按这个顺序执行
    • 全部写成功,Primary 回复 Client
  3. 租约快到期时,Primary 找 Master 续期

这样做的效果:

  • Master 不用参与每次写操作,压力小
  • Primary 统一协调顺序,所有副本写入顺序一致 → 数据一致
  • 并发追加时,Primary 负责合并顺序,每个追加操作原子性

读写流程

读操作(简单):

sequenceDiagram
    Client->>Master: 请求文件元数据(Chunk 列表及位置)
    Master->>Client: 返回 Chunk 列表及每个 Chunk 的 ChunkServer 地址
    Client->>ChunkServer: 直接请求读取目标 Chunk 数据
    ChunkServer->>Client: 返回 Chunk 数据

写操作(追加):

sequenceDiagram
    Client->>Master: 请求 Chunk 租约信息(获取 Primary 和 Secondary)
    Master->>Client: 返回 Primary 和 Secondary 地址
    Client->>Primary & Secondary: 推送数据到所有副本的缓存
    Client->>Primary: 发送写请求(请求执行追加)
    Primary->>Secondary: 通知写顺序,要求执行写操作
    Secondary->>Primary: 返回写成功响应
    Primary->>Client: 返回追加成功响应(包含实际写入位置)

关键点:数据先”推”到所有副本,再”通知”写。 这样数据已经在本地了,写操作只是顺序追加,速度快。

Master 的元数据怎么存的?全在内存里

Master 存三样东西:

  1. 文件命名空间:目录树、文件名
  2. 文件 → Chunk 映射:每个文件由哪些 Chunk 组成
  3. Chunk → ChunkServer 映射:每个 Chunk 在哪些节点上

前两样持久化到磁盘(操作日志 + 检查点),第三样不持久化——ChunkServer 启动时会把自己手里的 Chunk 列表上报给 Master。

为什么第三样不持久化? ChunkServer 会上下线、会故障,位置信息是动态的,靠心跳汇报更可靠。

GFS 与 HDFS 的对照

HDFS 就是 GFS 的开源实现,几乎照搬了设计:

GFS HDFS
Master NameNode
ChunkServer DataNode
Chunk(64MB) Block(128MB)
租约机制 无(写操作由 NameNode 协调,更简单但性能略低)
追加写为主 追加写为主,支持有限的随机写

欢迎关注我的其它发布渠道