OpenAI 如何扩展 Git:Pando 系统

OpenAI 的代码仓库在过去一年里增长和需求压力急剧上升。Codex 带来的并行开发让分支推送、抓取、克隆和 CI 请求同步暴增,原有的 monorepo 支撑系统在去年底开始吃紧:出现缓慢的 fetch 和 push、失败的合并,可靠性一度低于90%。为此 OpenAI 构建了名为 Pando 的 Git 后端,在不改变工程团队原有 Git 工作流的前提下,接管了整个 monorepo 的开发流量。Pando 的两个核心目标:水平扩展写入,支持大量并发 push 到不同分支;最大化读取吞吐,让客户端可以打满可用网络带宽。上线后,中位推送延迟降低近80%,系统每天交付接近 1PB 的 Git 数据。

设计上,Pando 保留了 Git 协议和客户端兼容。关键取舍是放弃两个常见假设:仓库级一致性和为每个客户端单独生成 packfile。Pando 采用因果一致性:只对单个 ref 的更新提供串行化,不同分支之间没有全局时间点概念;写入的 packfile 以不可变对象存入 blob store,ref 版本记入 metadata store(名为 Turtle)。抓取时直接挑选已存储的 packfile 返回,服务端无需 unpack 和 repack。相比 3PC 和 WAL 方案,Pando 避开了推送到无关分支时共享协调点的问题;模拟中 3PC 写入延迟随负载升高,WAL 读取延迟升高,而 Pando 在数千并发客户端下仍能保持稳定。Pando 服务器主要做协商和 pack 选择,可以跑在商品硬件上。

推送侧,Pando 默认只向客户端公布一个主干分支作为基础,因此生成的 packfile 可以被其他拥有该主干历史的读者复用。代价是连续推送或堆叠分支时会重复发送主干之外的冗余对象;在 OpenAI 的 monorepo 中,这种 packfile 的中位大小不到 20KiB,99 分位不到 3MiB。推送时先流式写入 blob store,同步更新 ref 版本和指针,保证 read-your-own-write;元数据读写均为 O(1)。无关分支的 ref 更新互不争锁,可通过增加 Pando 服务器、metadata 存储和 blob 存储扩展写吞吐。读取时,Pando 用 packfile-uri 让客户端并行下载多个 pack,配合名为 Express 的 pack 分发服务,缓存命中率超过99%,并在标准云虚拟机上验证了克隆和 fetch 能打满 10Gbps 网络链路。

为了避免客户端每次 fetch 都要下载大量小 pack,Pando 在后台做类似 LSM-tree 的压缩(compaction),把小包合并为从 L0 到 L4 的 cover 层。这些 cover 提高压缩率,也充当 ref 版本的跳表,使 fetch 的 pack 规划接近对数时间。与传统 Git 服务器不同,Pando 不清理旧 pack,而是让各层 pack 持续服务请求,只是读取高层包中的任意对象通常需要读取更多数据。

Pando 是使用 Codex 构建的:从启动到生产只用 10 周,核心由一名工程师设计,代理团队实现,最后由少数工程师部署,4 月开始承担生产流量。实现采用 Rust,没有历史依赖;团队写了面向代理的 Git 一致性测试套件,并开发了确定性模拟测试,代理还用 GPT-6 Astra 编写 Lean 和 TLA+,形式化 Pando 的理论,用来发现和修复 bug、证明系统性质。部署时先作为原有源码控制系统的读写代理,逐步迁移流量,同时迁移了数百个依赖旧 API、webhook 和仓库下载的集成。切换后合并可靠性改善,系统在单小时内服务超过 57TB 的 Git 数据,其中超过 99% 来自本地磁盘缓存。

Pando 也回馈了上游 Git 一批改进,包括 packfile-uri 下载的并发、清理和恢复,以及显式 haves 等,部分已合入上游 Git,其余在 OpenAI 的公开仓库和 patch tracker 中。OpenAI 还在探索 Pando 在 monorepo 之外的使用场景,尤其是大量 agent 协作的共享仓库,并计划向用户分享这项技术。

从整体设计看,Pando 的核心思路是:用因果一致性和 packfile 复用替代全局一致性和每客户端打包,让写入和读取分别向可水平扩展的方向走,同时保持与 Git 协议和客户端的兼容。这样工程师和 agent 无需改变既有工作流,就能在更大的并发规模下继续使用 Git。

Scaling Git at OpenAI

查看原文