基于公开资料的整理 · 《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 | +-------------------------------+ |
图中三条路径:(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 进程内,有三个直接好处:
- 元数据读写是进程内访问本地 tablet,少一跳 RPC;
- Curator 的分片天然跟随 Bigtable 的 tablet 划分,split、合并和负载均衡都由 Bigtable 自动完成;
- 某个 Curator 故障时,Bigtable 把对应 tablet 迁到别的 tablet server 上,Curator 随之”迁移”,不需要单独的 Curator 选主机制。
3.3 元数据模型
3.3.1 Bigtable 中的文件行
【官方】[A4] 给出了一个文件元数据的示意:
1 | Row key: /cfs/ex-d/home/denis/myfile |
要点:一个 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] 描述的分配流程:
- Curator 维护一张 load map,记录各存储节点的负载和存活状态;
- 需要分配 chunk 时(客户端需要更多空间、重平衡或恢复),Curator 生成一组候选存储节点,向每个候选节点发送 “allocate chunk” 请求;
- 存储节点如果过载或空间不足,可以拒绝;
- 被拒绝时,Curator 换一个节点重试。
Curator 掌握的存储节点状态包括 [P1]:容量、剩余空间、负载、从客户端视角看到的延迟、当前状态。获取方式有两种:直接查询存储节点,或者向客户端收集延迟统计。
【推断】”存储节点可拒绝”是一种分布式的准入控制:Curator 的 load map 不必实时精确,最终由存储节点根据本地真实状态拍板。”从客户端视角看到的延迟”说明放置决策会考虑网络拓扑和慢节点,不只看磁盘本身。
3.7 数据放置:维护层级
这是专利中写得最详细的部分,也与官方的宽条带 LRC 论文 [A10] 互相印证。
3.7.1 维护层级
【专利】[P2] Curator 会确定一个维护层级(maintenance hierarchy),标出在哪些层级上做维护不会影响用户访问数据。示例中有 5 级,从上到下:
1 | Level 1 power plant |
- 每个层级包含若干维护单元(maintenance unit),每个单元有 active / inactive 两种状态;
- 一个维护单元可以是由同一个配电单元或同一条母线槽(bus duct)供电的一组存储设备,也可以是同一个冷却单元覆盖的设备;
- 层级可以按电力划分,也可以按冷却划分,或两者组合;
- 一个机架可以同时属于多个维护单元(层级不一定是严格的树)。
[P5] 中的”系统层级”给出了另一种划分:第 1 级是主机(处理器、内存、网卡),第 2 级是机架的供电、通信、冷却设备,第 3 级是 cell 的供电、通信、冷却设备,第 4 级是配电中心模块。
3.7.2 放置算法
【专利】[P2][P3] 的核心思路:把一个文件(或一个 stripe 组)的 chunk 分散到多个维护单元上,保证任何一个(或阈值个)维护单元进入 inactive 状态时,文件仍然可以访问或重建。 具体有两种方法。
方法一,随机选择加校验:
- 随机选出与 chunk 数量相同的存储设备(可用简单抽样、概率抽样、分层抽样或整群抽样);
- 检查这组设备能否在一个(或阈值个)维护单元不可用时保持文件可访问;
- 不满足就重新随机选一组,或在原有选择上增删若干随机设备,直到满足为止。
方法二,有序环形列表:
- 预先构造一个有序环形列表,保证列表中相邻的存储设备属于不同的维护单元(或者连续若干个设备都属于不同维护单元或不同地理位置);
- 放置时从列表中取连续的 N 个设备,N 等于 chunk 数;
- 不满足约束就换一段连续设备。
另外还有一条简单约束:限制单个维护单元中能放的 chunk 数 [P2][P3]。
【官方】这与 FAST 2023 宽条带 LRC 论文的结论一致:同一 stripe 的多个块不能落在同一个维护域里,否则一次计划内维护(例如内核升级)就可能让 stripe 不可用 [A10]。
【推断】方法一实现简单、负载天然均匀;方法二把约束检查前移到离线构造列表的阶段,在线分配时几乎不用试错,适合宽条带(例如约 80 块的 LRC),因为宽条带随机选中合法组合的概率很低。
3.8 写者所有权与 fencing
【官方】[A3] 当新客户端以 append 模式打开一个正在被写的对象时:
- Curator 以事务方式在每个数据副本上递增版本号,把旧写者锁在外面;
- 旧写者再追加时会失败,因为它的所有权绑定在旧版本号上;
- 每次追加都带写入偏移量,保证网络分区和请求重放时数据仍然正确。
【推断】这里有两点值得注意:
- 版本号存在 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 个字校验块,单独成一列。
重建分两步:
- 列内重建:一列中损坏不超过 X 块时,只用本列的健康块和本列的列校验块即可修复;
- 跨列重建:某列损坏超过 X 块时,再动用字校验块。
专利的说明是:这样一来,只有当单个数据中心内损坏超过 X 块时,才需要跨数据中心通信(跨数据中心通信更慢、更贵)。
【推断】这种”局部校验 + 全局校验”的结构与后来的 LRC(局部可修复码)思路一致。宽条带 LRC 论文 [A10] 说明 Google 生产集群使用了宽度约 50 和约 80 的 LRC,嵌套码可以看作它的前身或同类设计。专利中”数据块 256 字节”的例子明显对应内存系统,不适用于磁盘上的 Colossus。
5.4 磁盘空间均衡与冷热迁移
【官方】PDSW 2017 [A4] 描述的目标是”让每块磁盘既满又忙”:每块盘上的热数据量相近(磁头都在忙),剩余空间用冷数据填满(盘都是满的)。实现方式是:
- 新写入的数据均匀分布到集群内所有磁盘(这一步发生在 Curator 分配 chunk 时);
- 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 参考资料
官方资料
- [A1] D. Hildebrand, D. Serenyi. Colossus under the hood: a peek into Google’s scalable storage system. Google Cloud Blog, 2021. https://cloud.google.com/blog/products/storage-data-transfer/a-peek-behind-colossus-googles-file-system
- [A2] L. Greenfield, S. Pollen. Colossus under the hood: How we deliver SSD performance at HDD prices. Google Cloud Blog, 2025. https://cloud.google.com/blog/products/storage-data-transfer/how-colossus-optimizes-data-placement-for-performance
- [A3] D. Serenyi, V. Saraswat. Colossus: the secret ingredient in Rapid Storage’s high performance. Google Cloud Blog, 2025. 转载:StorageNewsletter
- [A4] D. Serenyi. Cluster-Level Storage @ Google: How we use Colossus to improve storage efficiency. PDSW-DISCS 2017 Keynote. http://www.pdsw.org/pdsw-discs17/slides/PDSW-DISCS-Google-Keynote.pdf
- [A5] A. Fikes. Storage Architecture and Challenges. Google Faculty Summit, 2010. https://cloud.google.com/files/storage_architecture_and_challenges.pdf
- [A6] W. Look, M. Dallman. Case Studies in Infrastructure Change Management. Google SRE, 2020. https://sre.google/resources/practices-and-processes/infrastructure-change-management
- [A7] B. Beyer et al. Site Reliability Engineering, Chapter 2. O’Reilly, 2016. https://sre.google/sre-book/production-environment/
- [A8] T.-W. Yang et al. CacheSack: Admission Optimization for Google Datacenter Flash Caches. USENIX ATC 2022. https://www.usenix.org/system/files/atc22-yang-tzu-wei.pdf
- [A9] E. Brewer et al. Disks for Data Centers. Google White Paper, 2016. https://research.google.com/pubs/archive/44830.pdf
- [A10] S. Kadekodi et al. Practical Design Considerations for Wide Locally Recoverable Codes (LRCs). USENIX FAST 2023. https://www.usenix.org/system/files/fast23-kadekodi.pdf
专利
- [P1] Single-sided distributed storage system. US9229901、US9916279(Google;相关申请最早于 2012 年提交). https://freepatentsonline.com/9916279.html
- [P2] Distributing data on distributed storage systems. US10678647B2、US10318384(Google;优先权 2013-12-05). https://patents.google.com/patent/US10678647B2/en
- [P3] R. Cypher, S. Quinlan, S. R. Schirripa, L. Carmi, C. E. Schrock. Efficient data reads from distributed storage systems. US9323615(2014-01-31 申请). https://patents.google.com/patent/US9323615B2
- [P4] Prioritizing data reconstruction in distributed storage systems. US9292389. https://patents.google.com/patent/US9292389B2/en
- [P5] Efficient resource utilization in data centers. US9311194. https://patents.google.com/patent/US9311194B1/en
社区与论文
- [C1] Hacker News: Understanding Google’s File System (2020), 2024 年讨论. https://news.ycombinator.com/item?id=39756262
- T. Kim et al. Morph: Efficient File-Lifetime Redundancy Management for Cluster File Systems. SOSP 2024. http://www.pdl.cmu.edu/PDL-FTP/Storage/Morph_Final.pdf
- M. Marty et al. Snap: a Microkernel Approach to Host Networking. SOSP 2019. https://research.google/pubs/snap-a-microkernel-approach-to-host-networking/
整理日期:2026-11-07。本文是基于公开资料的学习整理,不代表 Google 官方观点;专利内容不等于生产实现,标注为推断的内容请结合原始资料核实。