Monorepo 双雄:Google Piper 与 Meta Sapling 的技术路径分野
Monorepo 双雄:Google Piper 与 Meta Sapling 的技术路径分野
在软件工程的世界里,代码版本控制系统是基础设施中的基础设施。
而当一家公司的工程师规模达到数万、代码量达到数十亿行时,普通的 Git 或 SVN 早已不堪重负。
Google 和 Meta(原 Facebook)——这两家全球最大的科技公司——各自走出了一条截然不同的 monorepo(单体仓库)之路:一个闭门自研、从未对外开源;另一个从开源社区出发,深度改造后又反哺社区。
这篇文章,我们来深入对比这两套系统,看看它们的设计哲学、技术路径和最终的取舍。
一、为什么是 Monorepo?
在深入两家的方案之前,先回答一个根本问题:为什么大厂都要把所有代码塞进一个仓库?
答案藏在工程效率里。Monorepo 的核心优势在于:
- 统一版本管理:所有代码共享一个版本号,不存在"这个库依赖那个库的哪个版本"的混乱
- 原子级变更:一个 API 的改动可以同时修改调用方,无需跨仓库协调
- 代码共享与复用:工具库、通用组件随手可用,不用每个团队造轮子
- 大规模重构:改一个接口,全公司所有调用点一起改,不会留下历史包袱
- 团队协作透明:你能看到别人在做什么,减少重复造轮子
但代价也很明显——当仓库大到一定程度,普通的版本控制系统会直接崩掉。Git 在百万级文件面前,git status 都能卡几分钟。
这就是为什么 Google 和 Meta 都不得不造自己的轮子。
二、Google Piper:自研到骨子里的代码巨兽
Piper 是 Google 内部使用的集中式版本控制系统,也是目前地球上规模最大的单体代码仓库的承载者。
规模有多夸张?
根据 2016 年发表在 ACM 上的论文数据:
| 指标 | 数字 |
|---|---|
| 数据总量 | 86 TB |
| 源代码行数 | 20 亿行 |
| 源文件数量 | 900 万个 |
| 提交历史 | 3500 万次 |
| 使用工程师 | 25000+ 人 |
| 每个工作日提交量 | 4 万次(1.6 万人提交,2.4 万次机器人提交) |
| 峰值文件读取 QPS | 80 万 |
这是什么概念?Linux 内核——公认的大型开源项目——也才 1500 万行代码、4 万个文件。Google 的代码库是它的两个数量级以上。
技术架构:从 Perforce 到自研
Google 不是一开始就有 Piper 的。
- 1990 年代:用 CVS
- 1999 年:换成 Perforce,靠一台主机加缓存层撑了十多年
- 2010 年代:规模实在太大,商业系统顶不住了,开始自研
Piper 的底层架构完全构建在 Google 自己的云基础设施上:
- 存储层:最初基于 Bigtable,后来迁移到 Spanner——Google 的全球分布式关系数据库
- 一致性:通过 Paxos 算法在全球 10 个数据中心之间保持副本一致
- 缓存与异步:大量使用缓存和异步操作来掩盖网络延迟
这意味着 Piper 从根上就是一个集中式系统——代码的唯一真相在服务器端,开发者本地只有工作区(workspace),而不是完整的仓库克隆。
CitC:云端工作区的魔法
Google 开发者日常接触 Piper 的主要方式是通过 CitC(Clients in the Cloud)。
这是一个基于 FUSE 的文件系统,它的神奇之处在于:
- 开发者看到的是"整个仓库 + 我的修改"的完整目录结构
- 但实际上本地平均只缓存了 不到 10 个文件
- 所有文件读写都通过云端映射,需要时才按需拉取
- 工作区是快照式的,可以随时回退到任意状态
这种设计让 Google 工程师几乎都采用 trunk-based development(主干开发)——没有个人分支,直接在主干上开发,靠特性开关(feature flag)隔离未完成的功能。分支只用于发布。
为什么 Piper 不开源?
Piper 至今仍是 Google 的内部系统,没有对外开源的计划。原因不难理解:
- 深度绑定内部基础设施:Piper 跑在 Spanner、Bigtable、Google 数据中心之上,这些都不是外部能轻易复现的
- 是结果而非产品:Piper 是为了解决 Google 自己的问题而存在的,不是一个可以卖的产品
- 生态封闭性:围绕 Piper 的代码评审(Critique)、构建系统(Blaze/Bazel)、静态分析等工具链形成了完整闭环,单独开源 Piper 没有意义
不过,社区里有一个叫 Mega 的开源项目,试图复刻 Piper 的设计理念,支持主干开发、约定式提交和代码所有者机制。
三、Meta Sapling:从 Mercurial 出发,回馈社区
与 Google 的全自研路线不同,Meta(Facebook)走了一条"站在巨人肩膀上"的路——从开源的 Mercurial 出发,深度改造后又回馈给社区。
起源:Mercurial 的 500 多个补丁
故事要从 2012 年说起。
当时 Facebook 的 monorepo 规模已经让现有的版本控制系统捉襟见肘。他们选择了 Mercurial 作为基础,原因是 Mercurial 的扩展性更好、Python 写的插件生态丰富。
但要支撑 Facebook 的规模,光靠原生 Mercurial 远远不够。于是 Meta 的工程师开始了漫长的改造之路——前后向 Mercurial 上游回馈了 500 多个补丁,涵盖性能优化、新功能、bug 修复等方方面面。
这些补丁不是小修小补,而是涉及存储格式、网络协议、算法等核心层面的改动。
随着改造越来越深入,Sapling 逐渐从"一个 Mercurial 分支"变成了"一个有自己灵魂的独立系统"。
从 hg 到 sl:彻底的重新设计
Sapling 的 CLI 工具叫 sl(smart log 的缩写),它完全重新设计了用户体验:
| Git 式体验 | Sapling 式体验 |
|---|---|
| 有暂存区(staging area) | 没有暂存区,sl commit 直接提交当前所有改动 |
| 提交是不可变的历史 | 提交是可以随意摆弄的草稿 |
git log 看整个历史 |
sl 只看你关心的本地提交,无关历史自动折叠 |
| 撤销操作复杂,依赖 reflog | sl undo、sl redo、sl uncommit、sl unamend——几乎所有操作都可以撤销 |
| 不想要的提交要删除 | sl hide 藏起来就行,想找回来随时 sl unhide |
| 堆叠式提交需要各种 rebase 技巧 | 提交栈是一等公民,可以轻松编辑栈中任意一个提交,自动 rebase 上面的提交 |
用 Meta 自己的话说:
"Git 教你把提交看作不可变的历史,Sapling 教你把提交看作可以随意摆弄的草稿。"
后端:Mononoke 与 EdenFS
Sapling 的后端也经历了彻底重写。核心组件包括:
- Mononoke:用 Rust 重写的 Mercurial 服务器端,性能比原生 Python 实现高几个数量级
- EdenFS:虚拟文件系统,类似 Google 的 CitC——让你感觉拥有整个仓库,但实际只下载了你用到的文件
这也是为什么 Sapling 能支撑 Meta 内部数千万文件、数千万提交、数千万分支的超大规模仓库。
开源策略:半开半闭
Sapling 的开源策略很有意思:
- ✅ CLI 客户端:已完全开源(GPL-2.0 协议),GitHub 上 6800+ stars
- ✅ Git 兼容:开源的
sl可以直接 clone 和操作 Git 仓库,你甚至可以用它来替代 Git 做日常开发 - ⏳ 服务端与 EdenFS:Meta 表示"未来希望开源",但目前还没有
这意味着外部用户目前只能用到 Sapling 的客户端能力,无法搭建自己的 Sapling 服务端来管理超大规模 monorepo。
但即使只是客户端,它的用户体验也已经让很多 Git 用户大呼"真香"。
四、两条路线的对比
| 维度 | Google Piper | Meta Sapling |
|---|---|---|
| 起源 | 完全自研(从 Perforce 迁移而来) | 基于 Mercurial 深度改造 |
| 开源状态 | 完全闭源,内部使用 | CLI 开源,服务端暂未开源 |
| 架构模式 | 集中式(CitC 云端工作区) | 分布式 + 虚拟文件系统 |
| 底层存储 | Spanner / Bigtable | 自定义对象存储 |
| 开发模式 | 主干开发,几乎不用分支 | 堆叠式提交(stacked commits) |
| 社区贡献 | 无 | 向 Mercurial 回馈 500+ 补丁 |
| 可复现性 | 几乎不可能,依赖 Google 基础设施 | 客户端可独立使用,服务端未来可能开源 |
| 规模 | 86TB、20 亿行代码、900 万文件 | Meta 内部数千万文件、数千万提交 |
五、殊途同归的启示
Google 和 Meta 走了两条完全不同的路,却在终点处达成了惊人的共识:
共识 1:Monorepo 是超大规模工程组织的必然选择
当你有几万工程师、几十亿行代码时,分散式的多仓库管理带来的协调成本会远远超过版本控制本身的成本。
跨仓库依赖、版本不兼容、API 变更无法同步推进、重复造轮子……这些问题累积起来的效率损失,大到你无法想象。
Monorepo 不是银弹,但到了那个规模,它是所有糟糕选择里最不糟糕的那一个。
共识 2:普通 Git 撑不住超大规模
两家都不得不自己造轮子——无论是 Google 的全自研,还是 Meta 的深度改造,本质上都是在解决同一个问题:
Git 的设计目标是 Linux 内核那种规模的项目,而大厂的代码库比它大两个数量级。
Git 的数据结构、网络协议、本地操作算法,在千万级文件面前,全都是瓶颈。
共识 3:虚拟文件系统是关键解法
无论是 Google 的 CitC 还是 Meta 的 EdenFS,核心思路都是一样的:
不要把整个仓库克隆到本地,按需加载、云端协同。
这也是为什么两家都走向了"伪集中式"的架构——表面上是分布式,实际上大部分操作都依赖云端。
当你本地只有你真正用到的那几十个文件时,操作速度自然就快了。
六、开源策略背后的企业文化
两家在开源策略上的选择,也折射出了各自的企业文化:
Google 更习惯把基础设施当作自己的核心竞争力,不轻易对外释放。
Piper、Bazel(开源的 Blaze)、Kubernetes、TensorFlow……Google 也开源,但它的开源策略是非常谨慎的。要么就是已经在内部用了十年成熟到不能再成熟,要么就是希望通过开源建立行业标准。
Meta 则更倾向于从开源社区汲取营养,再把成果回馈给社区。
React、PyTorch、GraphQL、Rust……Meta 对开源的态度要激进得多,也更愿意把自己内部在用的核心基础设施开源出来。500 多个 Mercurial 补丁就是最好的证明。
这两种策略没有高下之分,只是公司文化和战略的不同。
写在最后:对普通开发者的意义
对于普通开发者和中小团队来说,这些大厂的方案可能暂时用不上。你这辈子可能都不会遇到 900 万个文件的代码仓库。
但它们探索出的思路——堆叠式提交、可撤销操作、虚拟文件系统、主干开发——正在逐步渗透到主流工具中。
Sapling 的开源就是一个信号:下一代版本控制的用户体验,已经在路上了。
你今天可能还在用 Git,但是十年后,你用的版本控制系统,很可能已经吸收了 Piper 和 Sapling 的很多设计思想。
而这,就是大厂在基础设施上的投入,给整个行业带来的红利。
参考资源
- Why Google Stores Billions of Lines of Code in a Single Repository — ACM 论文,Google Piper 的官方介绍
- Sapling 官方网站 — https://sapling-scm.com/
- Sapling GitHub — https://github.com/facebook/sapling
- Mega — https://github.com/megascm/mega,复刻 Piper 设计理念的开源项目
- EdenFS 介绍 — Meta 官方博客,介绍虚拟文件系统的设计
作者: itech001 来源: 公众号:AI人工智能时代 网站: https://www.theaiera.cn/ 每日分享最前沿的AI新闻资讯和技术研究。
本文首发于 AI人工智能时代,转载请注明出处。