0%

Colossus 核心模块设计详解:Curator、D Server 与 Custodian

基于公开资料的整理 · 《Colossus 系统综述》的配套文档

阅读前须知:Google 没有公开过这三个模块的设计文档。本文把官方博客与演讲、Google 的一组分布式存储专利,以及前员工的公开评论拼在一起,尽量还原每个模块”做什么、怎么做”。

每条结论都标注了来源类别:【官方】 指 Google 官方博客、演讲、论文和 SRE 报告;【专利】 指 Google 的分布式存储专利;【社区】 指前员工等在公开社区的发言;【推断】 是本文作者的分析,官方没有直接确认。

专利是本文最大的信息来源,但它没有点名 Colossus,描述的也是一个以内存 + RDMA 为主要介质的系统,所以不能直接等同于生产 Colossus 的实现。第 1 节会专门说明为什么仍然值得参考。


1 资料来源与可信度

1.1 来源清单

编号 资料 类别 主要覆盖的模块
[A1] Colossus under the hood(Google Cloud 博客,2021) 官方 三个模块的职责定义
[A2] How Colossus delivers SSD performance at HDD prices(Cloud 博客,2025) 官方 Curator 的 SSD 放置与迁移
[A3] Colossus: the secret ingredient in Rapid Storage(Cloud 博客,2025) 官方 Curator 的 handle 与 fencing、D 的直连协议
[A4] Cluster-Level Storage @ Google(Serenyi,PDSW 2017 主题演讲) 官方 Curator 部署与元数据格式、数据均衡
[A5] Storage Architecture and Challenges(Fikes,2010) 官方 Node 层(D)职责、故障统计
[A6] Case Studies in Infrastructure Change Management(Google SRE,2020) 官方 D 的定位、部署与迁移
[A7] SRE Book 第 2 章 Production Environment(2016) 官方 D 的定位
[A8] CacheSack(USENIX ATC 2022) 官方论文 D 的 buffer cache、Flash Server
[A9] Disks for Data Centers(Google 白皮书,2016) 官方 D 对磁盘固件的需求
[A10] Practical Design Considerations for Wide LRCs(FAST 2023) 官方论文 维护鲁棒的放置
[P1] US9229901 / US9916279 Single-sided distributed storage system 专利 Curator、file descriptor、存储节点
[P2] US10678647 / US10318384 Distributing data on distributed storage systems(优先权 2013-12) 专利 维护层级与数据放置
[P3] US9323615 Efficient data reads from distributed storage systems(2014 申请) 专利 维护域与分组放置
[P4] US9292389 Prioritizing data reconstruction in distributed storage systems 专利 重建优先级、嵌套码
[P5] US9311194 Efficient resource utilization in data centers 专利 系统层级与作业管理
[C1] Hacker News 讨论 “Understanding Google’s File System”(2024),用户 the-rc、dekhn 的评论 社区 Curator 部署、Borg 配额

1.2 为什么专利值得参考,又为什么要谨慎

值得参考的理由:

  • 术语完全一致:专利使用 cell、curator、stripe、chunk、file descriptor 等术语,与 Google 官方描述 Colossus 时用的词汇一一对应 [A1][A4];
  • 发明人:[P3] 的发明人包括 Sean Quinlan(GFS 技术负责人,2009 年 ACM Queue 访谈中介绍”分布式 Master 新系统”的人)和 Robert Cypher(《Disks for Data Centers》的作者之一);
  • 结构一致:专利中”文件 → stripe → chunk”的三级结构、复制与纠删码并存、按维护域放置等设计,与官方资料 [A4][A10] 描述的 Colossus 吻合。

需要谨慎的理由:

  • 专利的主体是一个单边(single-sided)分布式存储系统:数据放在内存主机(memory host)的 DRAM 中,客户端通过 RDMA 直接读写,服务端 CPU 不参与 [P1]。这与以 HDD/SSD 为主的 Colossus 不同;
  • 专利只描述”可能的实现(in some implementations)”,不保证生产系统这样做;
  • 专利里没有 Custodian 这个角色:扫描、恢复、重平衡的决策都归给 Curator 或”处理器”。生产 Colossus 中这些后台工作由 Custodian 承担 [A1][A2]。

【推断】较合理的理解是:这组专利描述的是与 Colossus 同一个控制面架构家族的系统,可能是基于 Colossus 思想的内存存储系统,也可能是 Colossus 某个阶段的设计抽象。用它来理解 Curator 的数据结构和决策逻辑是合适的,但具体参数(例如 chunk 大小)不能照搬。


2 三个模块的分工总览

2.1 一句话定位

模块 一句话定位 类比 GFS
Curator 处理交互式控制操作的元数据服务,可水平扩展 GFS Master 的前台部分
D Server 唯一直接读写物理磁盘的进程,只负责存取数据 GFS chunkserver
Custodian 后台存储管理器,负责持久性、可用性和空间均衡 GFS Master 的后台部分(重新复制、重平衡、垃圾回收)

【官方】2025 年博客把 Curator 和 Custodian 都算作”Colossus 元数据服务”的组成部分:Curator 处理文件创建、删除等交互式控制操作,Custodian 维护数据的持久性、可用性和磁盘空间均衡 [A2]。

【推断】可以理解为:GFS 把前台元数据服务和后台维护都放在单一 Master 进程里;Colossus 把它拆成了两种独立扩展的角色,前台走低延迟路径,后台走高吞吐路径,互不争抢资源。

2.2 交互关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
                      +-------------------------------+
| Client Library |
| (encoding, RAID, handle) |
+---+------------------+--------+
(1) open/create | | (2) read/append via handle
delete | | (RDMA-like, direct)
v v
+------------------+ +-----------+ +-------------------------+
| Bigtable |<->| Curators | | D Servers (HDD / SSD) |
| (FS metadata, | | (control |--->| store chunks, checksum, |
| 1 row per file) | | plane) | | per-replica version |
+------------------+ +-----+-----+ +-----------+-------------+
^ | scan results / ^
| | work to schedule | (3) rebuild, rebalance,
| v | migrate, transcode
| +-----------+ |
+------------| Custodians|----------------+
+-----------+ (background)

图中三条路径:(1) 控制路径,只在 open/create/delete 时访问 Curator;(2) 数据路径,客户端拿到 handle 后直接读写 D Server,不经过 Curator;(3) 后台路径,Custodian 读取元数据并直接操作 D Server 完成重建和迁移。

【推断】Curator 和 Custodian 之间”扫描结果 / 待调度工作”的箭头来自专利描述:”扫描本身不修改元数据,而是为系统中的其他组件安排要做的工作” [P1][P4]。生产系统中二者具体如何交接,官方没有说明。


3 Curator:元数据与控制面

3.1 职责

综合 [A1][A2][A3][A4][P1][P4],Curator 的职责可以归纳为:

职责 说明 来源
交互式控制操作 文件创建、删除、open 等 官方 [A1][A2]
管理文件系统元数据 维护 file map(文件到 file descriptor 的映射) 官方 [A1];专利 [P1]
构造并下发 handle open 时返回包含数据所在磁盘地址的 handle 官方 [A3]
写者所有权管理 新写者接管时,在每个数据副本上递增版本号 官方 [A3]
chunk 分配 文件需要更多空间、重平衡或恢复时分配新 chunk 专利 [P1]
数据放置 按维护层级为 chunk 选择存储设备 专利 [P2][P3]
SSD 放置与迁移 按 L4 建议把新文件放到 SSD,到期后迁回 HDD 官方 [A2]
命名空间扫描 持续扫描自己负责的命名空间,检查完整性并安排工作 专利 [P1][P4]
存储节点状态跟踪 维护存储节点的负载与存活状态 专利 [P1]

3.2 部署形态

运行位置【官方】:CFS(Colossus File System)的 Curator 运行在 Bigtable 的 tablet server 中 [A4]。

数量随集群规模变化【社区】:一位前 Google 员工在 Hacker News 上解释 [C1]:

GFS 使用 5 个 Master,通常跑在 5 台专用机器上;Colossus 则使用数量可变的 Curator 来处理全部元数据工作(类似 Unix 中的目录项和 inode,与数据块分开)。Curator 只是普通的 Borg 任务,和 YouTube、Gmail 等其他服务的任务混部在一起。集群存储越多,流量越大,Curator 越忙。很小的集群可能 5 个以内就够了,到了数百 PB 就需要非常多的 Curator。

同一位评论者还提到 [C1]:Borg 要求每个身份(包括运行 Colossus 服务的系统账号)都有配额,所以需要一套机制,按存储集群规模大致成比例地给 Colossus 分配 CPU 和内存配额;集群缩容时会出现一些”有趣的情况”;监控整个存储栈也需要与集群规模成比例的资源,而且以更高优先级单独授予。

【推断】Curator 运行在 tablet server 进程内,有三个直接好处:

  1. 元数据读写是进程内访问本地 tablet,少一跳 RPC;
  2. Curator 的分片天然跟随 Bigtable 的 tablet 划分,split、合并和负载均衡都由 Bigtable 自动完成;
  3. 某个 Curator 故障时,Bigtable 把对应 tablet 迁到别的 tablet server 上,Curator 随之”迁移”,不需要单独的 Curator 选主机制。

3.3 元数据模型

3.3.1 Bigtable 中的文件行

【官方】[A4] 给出了一个文件元数据的示意:

1
2
3
4
5
6
Row key: /cfs/ex-d/home/denis/myfile
is-finalized? mtime, ctime, ...
encoding r=3.2
stripe 0: checksum, length -> chunk0 chunk1 chunk2
stripe 1: checksum, length -> chunk0 chunk1 chunk2
stripe 2: OPEN -> chunk0 chunk1 chunk2

要点:一个 Bigtable 行对应一个文件;文件由多个 stripe 组成,stripe 是复制组;stripe 有 open、closed、finalized 三种状态;文件系统元数据放在 Bigtable 的内存 locality group 中 [A4]。

3.3.2 专利中的 file descriptor

【专利】[P1] 描述的 file descriptor 字段,与上面的文件行可以对应起来:

字段 含义 与官方示意的对应
file state 文件状态 is-finalized?
data chunks 每个 stripe 的副本数(复制文件) encoding r=...
stripe length 每个 stripe 的字节数 stripe 的 length
sub-stripe length 每个 sub-stripe 的字节数 —
stripe 数组 每个 stripe 一个 protocol buffer,描述其中的副本 stripe N: ... -> chunk...

每个 stripe 的 protocol buffer 包含 [P1]:

  • stripe replica handle:副本的句柄;
  • 持有该副本的存储节点身份;
  • 该副本的当前状态。

此外 [P1][P4]:

  • file descriptor 中可以带一个 client key(例如 32 位),它对某个存储节点上的某个 chunk 唯一,客户端凭它直接读取该 chunk;
  • 复制文件的每个 stripe 是一个逻辑 chunk,被复制成多个副本;纠删码文件的每个 stripe 由多个 data chunk 和 code chunk 组成,合起来构成一个码字(code word);
  • 每个 stripe 的放置相互独立,与同一文件其他 stripe 的位置无关。

【推断】”每个 stripe 独立放置”意味着同一个文件的数据分散在大量磁盘上:读大文件时可以并行利用很多磁头,单盘故障时受影响的也只是零散的 stripe,重建负载会自然打散到全集群。

3.4 元数据访问模式

【专利】[P1][P2] Curator 对持久化元数据有三种访问模式:

模式 典型用途(推断)
只读(read-only) open、stat、查询数据位置
文件事务(file transactions) 创建、删除、finalize 等修改文件级属性的操作
stripe 事务(stripe transactions) 追加时新开 stripe、关闭 stripe、替换或迁移某个 chunk

【推断】把 stripe 级修改和文件级修改分开,符合 append-only 模型:日常追加只会修改”最后一个 stripe”,重建或迁移也只修改某个 stripe 的 chunk 列表,事务粒度小,冲突少。再加上一个文件就是一行,Bigtable 的单行原子性就足以保证这些事务的原子性,不需要跨行或分布式事务。

3.5 open 与 handle

【官方】[A3]:客户端创建或读取文件时,先 open 得到一个 handle。handle 是一组状态,包含文件存储方式的全部信息,包括数据在哪些磁盘上。之后读写都用 handle 直接和磁盘通信,走优化过的类 RDMA 网络协议。

【专利】[P1] 补充了失效处理:如果存储节点不可用,或者数据已经被迁到别的节点,客户端请求会失败,客户端随后重新向 Curator 查询。

【推断】这是一种”乐观缓存 + 失败重查”的设计:Curator 不需要在数据迁移时主动通知客户端(那样需要跟踪所有打开文件的客户端),代价是迁移后第一次访问多一次往返。这也是 Custodian 可以在后台自由迁移数据的前提。

3.6 chunk 分配

【专利】[P1] 描述的分配流程:

  1. Curator 维护一张 load map,记录各存储节点的负载和存活状态;
  2. 需要分配 chunk 时(客户端需要更多空间、重平衡或恢复),Curator 生成一组候选存储节点,向每个候选节点发送 “allocate chunk” 请求;
  3. 存储节点如果过载或空间不足,可以拒绝;
  4. 被拒绝时,Curator 换一个节点重试。

Curator 掌握的存储节点状态包括 [P1]:容量、剩余空间、负载、从客户端视角看到的延迟、当前状态。获取方式有两种:直接查询存储节点,或者向客户端收集延迟统计。

【推断】”存储节点可拒绝”是一种分布式的准入控制:Curator 的 load map 不必实时精确,最终由存储节点根据本地真实状态拍板。”从客户端视角看到的延迟”说明放置决策会考虑网络拓扑和慢节点,不只看磁盘本身。

3.7 数据放置:维护层级

这是专利中写得最详细的部分,也与官方的宽条带 LRC 论文 [A10] 互相印证。

3.7.1 维护层级

【专利】[P2] Curator 会确定一个维护层级(maintenance hierarchy),标出在哪些层级上做维护不会影响用户访问数据。示例中有 5 级,从上到下:

1
2
3
4
5
6
7
8
9
Level 1  power plant
|
Level 2 power module distribution center
|
Level 3 bus duct
|
Level 4 rack
|
Level 5 storage device
  • 每个层级包含若干维护单元(maintenance unit),每个单元有 active / inactive 两种状态;
  • 一个维护单元可以是由同一个配电单元或同一条母线槽(bus duct)供电的一组存储设备,也可以是同一个冷却单元覆盖的设备;
  • 层级可以按电力划分,也可以按冷却划分,或两者组合;
  • 一个机架可以同时属于多个维护单元(层级不一定是严格的树)。

[P5] 中的”系统层级”给出了另一种划分:第 1 级是主机(处理器、内存、网卡),第 2 级是机架的供电、通信、冷却设备,第 3 级是 cell 的供电、通信、冷却设备,第 4 级是配电中心模块。

3.7.2 放置算法

【专利】[P2][P3] 的核心思路:把一个文件(或一个 stripe 组)的 chunk 分散到多个维护单元上,保证任何一个(或阈值个)维护单元进入 inactive 状态时,文件仍然可以访问或重建。 具体有两种方法。

方法一,随机选择加校验:

  1. 随机选出与 chunk 数量相同的存储设备(可用简单抽样、概率抽样、分层抽样或整群抽样);
  2. 检查这组设备能否在一个(或阈值个)维护单元不可用时保持文件可访问;
  3. 不满足就重新随机选一组,或在原有选择上增删若干随机设备,直到满足为止。

方法二,有序环形列表:

  1. 预先构造一个有序环形列表,保证列表中相邻的存储设备属于不同的维护单元(或者连续若干个设备都属于不同维护单元或不同地理位置);
  2. 放置时从列表中取连续的 N 个设备,N 等于 chunk 数;
  3. 不满足约束就换一段连续设备。

另外还有一条简单约束:限制单个维护单元中能放的 chunk 数 [P2][P3]。

【官方】这与 FAST 2023 宽条带 LRC 论文的结论一致:同一 stripe 的多个块不能落在同一个维护域里,否则一次计划内维护(例如内核升级)就可能让 stripe 不可用 [A10]。

【推断】方法一实现简单、负载天然均匀;方法二把约束检查前移到离线构造列表的阶段,在线分配时几乎不用试错,适合宽条带(例如约 80 块的 LRC),因为宽条带随机选中合法组合的概率很低。

3.8 写者所有权与 fencing

【官方】[A3] 当新客户端以 append 模式打开一个正在被写的对象时:

  1. Curator 以事务方式在每个数据副本上递增版本号,把旧写者锁在外面;
  2. 旧写者再追加时会失败,因为它的所有权绑定在旧版本号上;
  3. 每次追加都带写入偏移量,保证网络分区和请求重放时数据仍然正确。

【推断】这里有两点值得注意:

  • 版本号存在 D Server 上的每个副本里,而不只是存在 Curator 的元数据中。即使旧客户端拿着缓存的 handle 绕过 Curator 直接写盘,也会在 D Server 处被拒绝。这是 Curator 与 D Server 协作完成的 fencing;
  • 递增版本号要触达所有副本,如果某个副本所在的 D Server 暂时不可用,Curator 很可能需要把该副本标记为失效,或者开一个新 stripe 继续写,具体做法官方没有说明。

3.9 SSD 放置与生命周期迁移

【官方】[A2]:

  • 用户可以通过路径参数强制放置,例如 partition=ssd(全部在 SSD)或 partition=ssd.1(只有一个副本在 SSD),Curator 据此选择介质;
  • 在 L4 writeback 模式下,L4 建议 Curator 新文件是否放 SSD、放多久;Curator 照此把新文件写到 SSD 而不是默认的 HDD;
  • 到期后如果文件仍然存在,Curator 把数据从 SSD 迁到 HDD;最好的情况是文件在迁移前就被删除,完全不产生 HDD I/O。

【推断】官方博客把这次迁移归给 Curator,而不是 Custodian。这说明”按策略到期迁移”属于 Curator 的职责范围,而 Custodian 侧重”维持健康状态”(冗余、均衡)。不过两者边界可能并不严格。

3.10 后台扫描

【专利】[P1][P4] 每个 Curator 持续扫描它负责的那部分命名空间,大约每分钟把所有元数据检查一遍。扫描的作用:

  • 检查元数据的完整性;
  • 找出需要做的工作(例如副本数不足的 stripe);
  • 生成统计信息。

扫描与 Curator 的其他操作并发进行;扫描本身不修改元数据,只是给系统中的其他组件安排工作,并计算统计数据。

【官方】这与 Fikes 2010 年的说法呼应:”元数据空间使可用性分析成为可能” [A5]。

【推断】”每分钟扫一遍”能做到,靠的是元数据放在 Bigtable 内存 locality group 中、且按 tablet 分片,每个 Curator 只负责一小段键空间。扫描产出的”待办工作”很可能就是 Custodian 的输入。

3.11 元数据的递归托管

【官方】[A4]:元数据约为数据量的 1/10000。100 PB 数据对应 10 TB 元数据,存进一个更小的 Colossus 需要 1 GB 元元数据,再往下是 100 KB,最后放进 Chubby。迁移初期,CFS 自己的元数据 Bigtable 还存在 GFS 上。


4 D Server:数据面存储节点

4.1 定位

【官方】综合 [A6][A7]:

  • D 是 Disk 的缩写,是 GFS chunkserver 的对应物;
  • D 是存储栈的最底层,被设计为唯一能直接读写物理磁盘的应用;
  • D 管理原始数据的访问,Colossus(Curator)管理”哪些数据在哪个 D 上”;
  • 客户端先向 Colossus 查询应读写哪些 D,然后直接和 D 通信;
  • D 同时使用 HDD 和 flash;
  • D 运行在集群中几乎所有机器上(2016 年的描述)[A7]。

4.2 职责:Node 层存储

Fikes 2010 年的幻灯片 [A5] 把存储栈最底层称为 “Node Storage”,用途是”把磁盘导出到网络上”,并列出了职责。结合 SRE 书对 D 的描述 [A7],这一层就是 D:

职责 原文 说明(推断)
导出并校验磁盘 Exports and verifies disks 网络化磁盘,加上端到端校验和
上层存储的构件 Building-block for higher-level storage Colossus、Bigtable 等都构建在它之上
磁盘访问性能调优的单一入口 Single spot for tuning disk access performance I/O 调度、合并、预取都集中在这里做
节点增删与维修管理 Management of node addition, repair and removal 配合排空(drain)与重建
用户资源计费 Provides user resource accounting (e.g. I/O ops) 按用户统计 I/O 次数
跨用户资源共享控制 Enforces resource sharing across users 多租户 I/O 隔离

【社区】D “更像块服务器而不是文件服务器”,”除了校验和之外基本不提供别的功能”(非官方,来自前员工的博客)。

4.3 部署形态的演变

阶段 形态 来源
迁移前 GFS chunkserver 不跑在 Borg 上;早期也有”chunkserver 支撑的 Colossus cell” 官方 [A6];社区 [C1]
2008 年起 D 作为 Borg 任务运行,和用户作业混部;为了给 D 腾出资源,专门做了 Steamroller 项目回收 Borg 配额 官方 [A6]
混部时期的问题 低端机器(例如 Nocona 平台)资源不够同时跑存储栈和用户作业,任务调度不上去,集群”看起来像少了一些磁盘” 社区 [C1]
2013 年起 部署第一代”存储专用硬件”:只提供远程存储、不跑本地计算的磁盘服务器,显著改善尾延迟 官方 [A6]
2012–2018 Diskless 项目移除计算节点本地盘,生产任务死亡中 25%–30% 曾归因于磁盘故障 官方 [A6]
现在 D Server 托管 HDD 或 SSD [A2];2021 年博客称其为”网络附加磁盘” [A1] 官方

【推断】D 从”混部在计算节点上的守护进程”演进为”跑在存储专用硬件上的服务”,这是计算存储解耦的关键一步:D 的性能不再受同机用户作业的 CPU 和内存干扰,尾延迟更可控。

4.4 数据面协议

【官方】[A3]:客户端用 handle 中的磁盘地址,通过优化过的类 RDMA 网络协议直接与磁盘通信,协议细节见 Snap 论文(Google 的用户态主机网络栈,其数据面引擎为 Pony Express)。追加写时客户端并行写所有副本,用 quorum 技术避免等待慢节点。

【专利】[P1] 中的单边存储模型可以作为参考:

  • 存储节点上的进程把一组内存区域注册到网卡,可设为只读或读写;网卡为每个注册区域生成一个 client key;
  • 连接建立后,客户端通过网卡硬件直接访问注册的内存,存储节点的 CPU 完全不参与;
  • 网卡单边操作只支持简单的读、写和 compare-and-swap,客户端库负责把”查找、插入”等高层命令翻译成一串网卡原语操作;
  • 好处是存储节点 CPU 再忙,读请求的延迟也低且可预测。

【推断】HDD/SSD 上的 D Server 不可能像 DRAM 那样完全单边访问,因为磁盘 I/O 需要软件调度。但”客户端持有凭证直接访问存储节点、不经过元数据服务”的思路是一致的。2025 年博客说”类 RDMA”而不是”RDMA”,也暗示 D 的协议是 RDMA 风格的语义(低开销、内核旁路),由 Snap/Pony Express 在软件中实现,而不是纯硬件单边操作。

4.5 写入正确性:校验和与版本号

  • 校验和【官方】:元数据中每个 stripe 记录了 checksum [A4];Node 层的职责里明确包括”校验磁盘” [A5];
  • 副本版本号【官方】:fencing 依赖”每个数据副本上的版本号”[A3],所以 D Server 必须为每个副本保存版本号,并在写入时比对;
  • 偏移量检查【官方】:每次追加都带写入偏移量 [A3],D Server 侧应能据此拒绝重复或乱序的写入(推断)。

【专利】[P1] 中客户端读到损坏副本时会通知 Curator;Curator 尝试重建该副本,无法重建时用一个新的未初始化副本替换它。

4.6 Buffer cache 与预取

【官方】[A8]:D Server(论文中称 Disk Server)的 buffer cache 会把最近访问的数据缓存几秒,并预取少量数据,所以读刚访问过的数据不一定产生磁盘读。Google 鼓励 Colossus 用户在设计负载时利用这层缓存。

CacheSack 在估算 flash cache 的收益时,专门对每个 cache index server 维护了一个 buffer cache 模拟器,以免把本来就会命中 D 内存缓存的访问误算为磁盘读 [A8]。

4.7 HDD 与 SSD 两类 D Server

类型 用途 来源
HDD D Server 承载绝大部分容量;新数据均匀打散,冷数据迁往大盘 官方 [A2][A4]
SSD D Server partition=ssd 强制放置、ssd.1 混合放置中的 SSD 副本、L4 writeback 写入的新文件 官方 [A2]
Flash Server(L4 读缓存) 存放 L4 读缓存数据,被准入时直接从 Disk Server 拉取数据 官方 [A2][A8]

【推断】Flash Server 很可能就是 SSD 介质上的 D Server,或者是复用 D 协议的独立服务。CacheSack 论文说缓存块存放在”固定大小的 Colossus 文件(通常 1 GiB)”中 [A8],说明 L4 缓存本身也是以 Colossus 文件的形式存在 SSD 上的。

4.8 D 对磁盘硬件的诉求

《Disks for Data Centers》白皮书 [A9] 从存储服务的视角向磁盘厂商提出了需求,可以看作 D 这一层在磁盘管理上的关注点:

白皮书提议 与 D 的关系(推断)
关注”磁盘集合”而不是单盘 数据已经有冗余,单盘可以容忍更高误码率,以换取容量或性能
主机管理的读重试(host-managed read retries) 读一块数据失败时,与其让磁盘固件长时间重试,不如由上层立即从其他副本或编码块读,改善尾延迟
后台任务与后台管理 API 磁盘自身的后台扫描等任务应该能被 D 调度,避免干扰前台 I/O
优化队列管理 提升 IOPS
灵活容量、更大扇区 提升容量与 TCO

4.9 准入与负载反馈

【专利】[P1]:存储节点在过载或空间不足时可以拒绝 chunk 分配请求;Curator 会查询存储节点的容量、剩余空间、负载和状态。

【官方】PDSW 2017 的集群可视化以”每个 D Server 一个方块、大小表示磁盘容量、颜色表示磁头利用率”的方式呈现集群状态 [A4],说明每个 D 的磁头利用率是存储效率优化的核心观测指标。


5 Custodian:后台存储管理

5.1 定位与职责

【官方】Custodian 是后台存储管理器 [A1],维护数据的持久性和可用性以及磁盘空间均衡 [A2],具体任务包括磁盘空间均衡和 RAID 重建 [A1],同时维持整体效率。

公开资料中与 Custodian 相关的工作可以归为四类:

工作 依据
冗余恢复(RAID 重建) 官方 [A1];重建策略见专利 [P4]
磁盘空间均衡 官方 [A1][A2]
冷数据向大容量磁盘迁移 官方 [A4](”Colossus rebalances old, cold data”),未明确说由 Custodian 执行(推断归属)
冗余方案转换(转码) 由应用决定 [Morph 论文],Custodian 是否参与执行未公开

5.2 冗余恢复:先等一等,再按风险排序

5.2.1 为什么要等

【官方】Fikes 2010 年引用 Storage Analytics 团队的数据 [A5]:

  • 90% 的故障事件持续不到 10 分钟,所以”在启动恢复操作前先等一等是值得的”;
  • 10% 的故障属于相关性突发;大的突发通常与机架高度相关;
  • 有相关性故障时,副本数从 2 增加到 3,MTTF 只提升 11 倍(无相关性时提升 3500 倍)。

5.2.2 有效冗余度与两级优先级

【专利】[P4] 给出了一个完整的重建优先级算法,正好对应”先等一等,但高风险的立刻修”:

第一步,为每个 stripe 计算有效冗余度(effective redundancy),即在当前状态下还能再承受多少个故障域失效:

stripe 类型 有效冗余度的计算方式
复制 stripe 至少还有一个可用副本的不同故障域的个数
纠删码 stripe(机架级) 在该层级中,还能有多少个故障域进入 inactive 状态而数据仍可访问
纠删码 stripe(cell / 配电级) 找出包含该 stripe 最多 chunk 的那个故障域,按它失效的情况计算;有多个并列时随机选一个
嵌套码 stripe 分别计算”列有效冗余度”(列内能由其他块重建的块数)和”stripe 有效冗余度”

第二步,按数据的可用性等级和有效冗余度分两级处理:

优先级 处理对象 时机
第一优先级 高可用等级数据中,有效冗余度低于阈值的不可访问 chunk 立即重建
第二优先级 低可用等级数据的不可访问 chunk;以及有效冗余度不低于阈值的高可用数据 chunk 等待一个时间阈值后再重建,专利给出的例子是约 15–30 分钟

此外 [P4]:

  • 故障域进入 inactive 状态时(计划内维护、计划外故障或其他原因),要更新所有相关 stripe 的有效冗余度;
  • “损坏的 chunk”包括被纠错码检测出错误的 chunk、整盘丢失的 chunk,以及因所在主机被关机维护而暂时不可用的 chunk,后者可以通过”哪些主机正在关机”直接识别。

【推断】这一机制把”等待”和”风险”结合了起来:大多数短暂故障在等待期内自行恢复,节省了大量无谓的重建流量;而真正危险的 stripe(再坏一块就丢数据)不等待,立即修复。15–30 分钟的等待窗口与”90% 的故障在 10 分钟内结束”的统计相吻合。

5.3 嵌套码与局部重建

【专利】[P4] 描述了一种嵌套码(nested code)结构:数据块排成二维数组,每列有 X 个列校验块(code-check chunk),整个数组另有 Y 个字校验块(word-check chunk),还可以为字校验块再生成列校验块。

专利中的示例:42 个数据块(D0–D41)加 8 个校验块(C0–C7),共 50 块,构成一个码字;数据块分成 7 列,每列配 2 个拆分的列校验块(由 C0、C1 拆分得到),C2–C7 为 6 个字校验块,单独成一列。

重建分两步:

  1. 列内重建:一列中损坏不超过 X 块时,只用本列的健康块和本列的列校验块即可修复;
  2. 跨列重建:某列损坏超过 X 块时,再动用字校验块。

专利的说明是:这样一来,只有当单个数据中心内损坏超过 X 块时,才需要跨数据中心通信(跨数据中心通信更慢、更贵)。

【推断】这种”局部校验 + 全局校验”的结构与后来的 LRC(局部可修复码)思路一致。宽条带 LRC 论文 [A10] 说明 Google 生产集群使用了宽度约 50 和约 80 的 LRC,嵌套码可以看作它的前身或同类设计。专利中”数据块 256 字节”的例子明显对应内存系统,不适用于磁盘上的 Colossus。

5.4 磁盘空间均衡与冷热迁移

【官方】PDSW 2017 [A4] 描述的目标是”让每块磁盘既满又忙”:每块盘上的热数据量相近(磁头都在忙),剩余空间用冷数据填满(盘都是满的)。实现方式是:

  1. 新写入的数据均匀分布到集群内所有磁盘(这一步发生在 Curator 分配 chunk 时);
  2. Colossus 把老的冷数据重新均衡到大容量磁盘上(这一步是后台工作,推断由 Custodian 执行)。

【官方】2021 年博客 [A1] 也说:新写入的(较热的)数据均匀分布到所有磁盘,数据变老、变冷后被重新均衡并迁到大容量磁盘上。

【官方】PDSW 2017 还列出了”填满磁盘”的现实约束 [A4]:文件系统在 100% 满时工作不正常;没有空闲空间就无法为升级和维修下线容量;各团队不愿意贴着 100% 配额运行;管理员对统计超卖心存顾虑;供应链存在不确定性。这些约束决定了 Custodian 的均衡目标不是”100% 满”,而是保留一定余量。

5.5 排空与维护配合

【专利】[P1][P4]:纠删码可以用来维护数据完整性、为了降低延迟而重建数据,或者更快地排空(drain)机器。

【推断】排空一台机器时,不一定要从这台机器上把数据读出来再写走(这台机器可能已经很慢或即将下线),可以用同一 stripe 中其他节点上的数据块和校验块,在别处重建出这台机器上的 chunk,把读负载分散到很多台机器上。这也是 Custodian 可能使用的手段。

5.6 冗余方案转换(转码)

【论文】Morph(SOSP 2024,CMU 与 Google 合作)分析了 Google 集群中一个最大的数据服务,发现典型的冗余生命周期是:写入时 3 副本,约 1 天后转为窄 RS(如 RS(8,12)),约 1 个月后转为中等 LRC(如 LRC(32,38)),数个月后转为宽 LRC(如 LRC(64,74))。论文指出:

  • 冗余方案由应用(数据服务)决定,而不是由文件系统决定;
  • 大多数文件系统不把转码作为原生操作,应用的做法是读出数据、用新编码写入新文件、删除旧文件。

【推断】如果 Colossus 也是这样,那么转码的 I/O 主要由应用发起,Custodian 只负责新文件的冗余维持。是否存在由 Custodian 执行的原生转码,公开资料没有说明。


6 三模块协作的典型流程

6.1 创建并追加写

步骤 执行者 动作
1 客户端 → Curator 以 append 模式创建或打开文件
2 Curator 按路径参数或 L4 建议选择介质(HDD/SSD),按维护层级选择 D Server,向候选 D 发 allocate chunk 请求(D 可拒绝)[P1][A2]
3 Curator → 客户端 返回 handle(含磁盘地址),客户端在进程内缓存 [A3]
4 客户端 → D Server 用 handle 并行写所有副本,带写入偏移量,quorum 确认后返回 [A3]
5 Curator 写满一个 stripe 后关闭它,新开 stripe(stripe 事务);文件写完后 finalize [A4][P1]

6.2 读与降级读

步骤 执行者 动作
1 客户端 → Curator open,取得 handle(只读元数据访问)
2 客户端 → L4 可选:查询 SSD 读缓存,命中则从 Flash Server 读取 [A2]
3 客户端 → D Server 直接读取所需 chunk;D 可能命中自己的 buffer cache [A8]
4 客户端 某个 chunk 读失败或太慢时,读同一 stripe 的其他数据块和校验块在线重建(推断,依据”纠删码可用于降低延迟的重建” [P4])
5 客户端 → Curator 如果 D 不可用或数据已迁移,重新向 Curator 查询 [P1]

6.3 磁盘故障

时间 执行者 动作
t0 D / 客户端 磁盘或主机失效;客户端读写失败后绕开该 D
t0 + 约 1 分钟 Curator 命名空间扫描发现相关 stripe 冗余不足,更新有效冗余度,安排工作 [P1][P4]
立即 Custodian(推断) 有效冗余度低于阈值的高可用数据立即重建:读取健康块,在新的 D 上写出缺失的 chunk
约 15–30 分钟后 Custodian(推断) 故障仍未恢复时,重建其余数据;如果故障已经恢复,就不必重建 [P4][A5]
重建完成 Curator stripe 事务:更新 chunk 列表,旧位置作废

6.4 计划内维护

步骤 说明
放置阶段 数据放置时已经保证一个维护单元整体下线也不影响可访问性 [P2][P3][A10]
维护开始 相关维护单元进入 inactive 状态;落在其中的 chunk 被视为”暂时损坏”,各 stripe 的有效冗余度随之更新 [P4]
维护期间 只有有效冗余度跌破阈值的 stripe 才立即重建;其余等待维护结束
维护结束 维护单元恢复 active,有效冗余度恢复,无需重建

7 与 GFS、HDFS、Tectonic 的模块对照

职能 GFS Colossus HDFS Tectonic(Meta)
前台元数据 单 Master(另有只读 shadow master) Curator(数量随集群规模变化,运行在 Bigtable tablet server 中) NameNode(可选 Federation) Name / File / Block 三层元数据服务
元数据存储 Master 内存 + 操作日志 Bigtable(内存 locality group) NameNode 内存 + EditLog ZippyDB
后台维护 Master 内部线程(重新复制、重平衡、GC) Custodian(独立角色) NameNode 内部(ReplicationMonitor 等)+ Balancer 工具 后台服务(rebalancer、repair 等)
数据节点 chunkserver(本地 Linux FS) D Server(唯一直接访问磁盘的进程;HDD/SSD;后来运行在存储专用硬件上) DataNode Storage Node
数据写入 chunkserver 流水线复制 客户端并行写 + quorum DataNode 流水线复制 客户端直写
位置信息来源 Master 重启时向 chunkserver 收集(需 10–30 分钟) 持久化在元数据中,open 时一次下发 DataNode 块报告 持久化在元数据中
写者控制 lease + 主副本 版本号 fencing(存在每个副本上) lease 单写者 + 序号

【推断】从对照表可以看出 Colossus 最本质的两点变化:一是把 GFS Master 的前台和后台拆开,分别由 Curator 和 Custodian 独立扩展;二是位置信息从”D 汇报给 Master 的软状态”变为”持久化在 Bigtable 中的硬状态”,消除了 GFS Master 重启时长达 10–30 分钟的位置收集过程。


8 尚未公开的关键问题

模块 问题
Curator 每个 Curator 负责的命名空间如何划分?是否严格对应 tablet?跨 tablet 的操作(如果有 rename)怎么处理?
Curator quorum 写的副本数、成功阈值,以及副本间数据不一致时如何收敛(谁来补齐落后的副本)?
Curator fencing 时如果某个副本不可达,如何处理?
D Server 磁盘上的数据布局:是直接管理裸盘,还是建在本地文件系统上?chunk 在盘上如何组织?
D Server 多租户 I/O 调度和配额是怎么实现的(Fikes 2010 年把它列为未解决的挑战)?
D Server 加密在哪一层做(SRE 书提到 Colossus 提供加密)?
Custodian 与 Curator 的分工边界:扫描在 Curator,执行在 Custodian,还是两者都会扫描?
Custodian 重建流量与前台流量的隔离和限速方式?
Custodian 是否执行原生转码?冷数据迁往大盘的触发条件是什么?

9 参考资料

官方资料

专利

社区与论文


整理日期:2026-11-07。本文是基于公开资料的学习整理,不代表 Google 官方观点;专利内容不等于生产实现,标注为推断的内容请结合原始资料核实。

如果对您有帮助