返回博客列表

Cursor 27分钟讲透Git托管:代码平台的竞争正在沉入对象存储

2026-08-15T01:30:00+08:00
CursorGitOriginS3对象存储基础设施Continuity

Cursor 27分钟讲透Git托管:代码平台的竞争正在沉入对象存储

后端和平台同学必看,这篇讲的是代码代理底层真正难在哪。

昨天 Cursor 发布了 Origin——代码托管平台,产品层的动作。今天这篇 27 分钟的技术博文,作者 Vicent Martí,讲的是产品下面的地基:Git 在大规模托管场景下到底难在哪。

结论先行:代码代理平台要做好,不是「多放几台机器」。核心瓶颈落在 packfile、DAG 遍历、网络传输和对象级存储。Cursor 的解法叫 Continuity——一个以 S3 为真相源(source of truth)的 WAL(Write-Ahead Log)系统。

本文提纲

  1. Git 托管为什么是噩梦
  2. 三条路线:分布文件系统、分布 packfile、分布 Git 本身
  3. GitHub 走过的弯路
  4. Spokes:GitHub 的 13 年老兵
  5. Spokes 在 2026 年的两个致命缺陷
  6. Continuity:Cursor 的 WAL 革新
  7. 数据:100 副本线性扩展,300+ pushes/s
  8. 为什么编码平台之争正在沉入对象存储

Git 托管为什么是噩梦

Git 的设计假设是:Linus Torvalds 管理 Linux 内核。内核是一个极端去中心化的项目,有大量子系统维护者,分布式版本控制是自然选择。

20 年后,Git 成了行业标准,但分布式设计对托管场景来说更多是阻碍。普通开源项目和公司都用集中式托管——一个中心 host,所有人推和拉。

问题出在 packfile。Git 的所有内容(文件、提交、树)压缩后存在 packfile 里——一个大二进制文件,必须存在于文件系统上才能被 Git 访问。packfile 既是存储格式也是网络传输格式:你 push 或 fetch 的数据都是 packfile。

一个直觉想法是:HTTP 服务放在磁盘上的 Git 仓库前面就搞定了。确实可以跑,但天花板极低。理想情况你希望仓库存在于多台机器的多个磁盘上——并行跑 Git 操作,机器挂了仓库还在。但怎么做到?

三条路线:分布文件系统、分布 packfile、分布 Git 本身

文章把三条路线按复杂度递增排列:

路线一:分布文件系统。 把仓库放在 NFS/GFS/DRBD 上,让多台机器共享文件系统。GitHub 早期试过,全部失败——Git 的随机读模式(在 packfile 里跨 GB 数据跳来跳去)和网络文件系统天然冲突。

路线二:分布 packfile。 不动文件系统层,在应用层做复制——GitHub 的 Spokes 方案,后文详述。

路线三:分布 Git 本身。 Git 是内容寻址存储(SHA-1 为 key,对象为 value),直觉上映射到分布式 KV 存储很干净。但行不通——Git 的数据布局是有向无环图(DAG),你不知道下一个指针的值,除非先取出上一个。每次 fetch 都是一次网络往返,54 个对象就是 54 轮往返。

Google 用 JGit + 分布式哈希表试过路线三,系统跑得起来,但 git clone 性能差到放弃整个设计——因为 Git 协议要求 packfile 在网络上传输,不管你服务端怎么存。

GitHub 走过的弯路

2008 年 GitHub 成立,标语是「Git repository hosting: no longer a pain in the ass」(不开玩笑,原文如此)。

早期架构:Rails 单体 + 单台机器 + 磁盘上的仓库副本。扩展 Rails app 很简单——多部署几个实例。但 Git 仓库在磁盘上,怎么多副本?

NFS:直接丢弃。Git 对文件系统语义的假设(锁、撕裂、读、同步)在本地文件系统上表现正常,在 NFS 上慢且 bug 多。

GFS:短暂部署,放弃。

DRBD(块级复制):部署时间最长,但运维噩梦,性能不好。

根本原因:packfile 在磁盘上的布局和 DAG 图结构之间没有相关性。packfile 里的对象是随机放置的、压缩的、大部分以 delta 形式存储——读一个对象要先跳图再跳磁盘,在百 GB 数据上随机跳,网络文件系统扛不住。

GitHub 最终放弃分布文件系统,转向 RPC 系统:仓库放在专用 fileserver 上,Rails app 远程操作。解决了水平扩展,但每个仓库仍只在单台机器上——可用性没解决,忙仓库的性能也没解决。

Spokes:GitHub 的 13 年老兵

2013 年 GitHub 开发 Spokes,后来成了行业标准。大多数 Git 托管服务的架构都是 Spokes 的变体。

Spokes 的三个核心选择,事后证明都是最优的:

  1. 不动 Git 本身,在 packfile 层做复制
  2. 仓库作为普通 Git 仓库存在本地 NVMe 磁盘上(随机读模式要求本地高速存储)
  3. 所有副本保持强一致(Git 客户端和最终一致性天然冲突)

强一致性的实现方式是 3PC(三阶段提交)。push 时,编排器把 packfile 扇出到所有副本(不需同步),然后用 3PC 对引用事务(reference transaction)做共识——引用事务比 packfile 小得多快得多。3PC 保证要么所有节点提交,要么所有节点回滚。

13 年来 Spokes 运行良好。但 2026 年的用法变了。

Spokes 在 2026 年的两个致命缺陷

缺陷一:3PC 的水平扩展天花板。

3PC 作为共识算法,每一步的延迟被集群中最慢的服务器决定。副本越多,push 吞吐越差——尾延迟在大规模下是杀手。

2013 年,3 个副本是最优配置。2026 年,企业公司的平均仓库是巨型 monorepo,3 个副本扛不住 CI 流量。但加副本?3PC 让 push 吞吐劣化。

反过来也是问题:Agent 时代会创建海量小仓库——大多数一次性、几乎不碰。Spokes 对每个仓库仍需 3 个副本,3 个基本空闲的副本不能缩减(否则不满足强一致性,有数据丢失风险)。

3PC 的地板太高,天花板太低。

缺陷二:仓库是宠物不是牛。

磁盘上的仓库是共识的真相源,每个副本都很重要。你需要:精确知道每个仓库在哪台机器上(路由表依赖外部数据库),持续校验每个仓库的 checksum,坏了要快速检测和修复。一旦 3 份里有 2 份损坏,就没有 quorum 了,系统拒绝 push。

Continuity:Cursor 的 WAL 革新

Continuity 是 Cursor 开发的 Git 存储系统,核心设计:以 S3 为真相源的 Write-Ahead Log。

graph TB
    A["Git Client Push"] --> B["WALGit Primary
receive pack"] B --> C["Write WAL entry to S3"] C --> D["Prepare ref txn
on local NVMe repo"] D --> E["Update WAL index
in S3 (CAS)"] E --> F["Acknowledge push
linearizable"] C --> G["UDP Gossip
to replicas"] G --> H["Replica
catch up from S3"] H --> I["Serve reads
verified via ETag 304"] style A fill:#FF6B6B,color:#000000 style B fill:#4ECDC4,color:#000000 style C fill:#45B7D1,color:#000000 style E fill:#45B7D1,color:#000000 style F fill:#96CEB4,color:#000000 style H fill:#FFEAA7,color:#000000 style I fill:#FFEAA7,color:#000000

核心设计决策

真相源是 S3,不是磁盘。 仓库在本地 NVMe 上是暖缓存,真相永远是 WAL。仓库丢失了?从 WAL 重新物化。路由表?不需要——用 rendezvous hashing 映射,失同步也无所谓。

没有共识协议。 不需要选主、不需要 3PC。任何服务器都能当 primary,S3 的 CAS(compare-and-swap)保证原子性。设计目标是:降级时永远正确,健康时永远快。

副本数无上限。 所有副本直接从 S3 追赶。用 UDP gossip 通知副本有新数据——UDP 不可靠没关系,读操作时用 conditional GET + ETag 验证:304 表示已最新(<10ms 的元数据操作),200 表示需要追。所有副本的所有读都是强一致的,因为都对着 S3 验证。

大 monorepo: 部署 100 个副本扛 CI 流量。 百万小仓库: 每个只 1 个副本。空闲仓库连 1 个都不需要——GC 掉,下次 fetch 时从 WAL 物化。

压缩(Compaction): 只有 primary 做,结果同时应用到磁盘和 WAL。副本不 repack——直接从 S3 下载已压缩的 packfile,用带宽换 CPU。不会再有维护操作导致 failover。

数据:100 副本线性扩展,300+ pushes/s

指标 S3 Standard S3 Express One Zone
Push 吞吐 120 pushes/s 300+ pushes/s
读扩展 100 副本线性 100 副本线性
一致性 全部强一致 全部强一致
追赶延迟 ETag 304 <10ms ETag 304 <10ms

压力测试跑到 100 个副本,读吞吐线性增长,push 吞吐无回退。S3 Express One Zone 上 push 瓶颈已经是 Git 压缩本身的速度了。

为什么编码平台之争正在沉入对象存储

这篇文章的信息量远超一篇产品发布稿。它讲的是:代码平台的护城河正在从产品层沉入基础设施层。

第一,Git 托管是 AI 编程时代被忽视的瓶颈。 文章最后一段说得很直接:Agent 改变了软件的工作方式——更多代码、更多 PR、更多 CI 运行。版本控制是这一切的核心,也是最难一夜之间改变的东西。Agent 创建海量小仓库(Spokes 扛不住),monorepo 流量暴增(3PC 扛不住),Git 托管基础设施的弹性变成了 AI 编程平台的天花板。

第二,对象存储成为 Git 托管的真相源。 Azure DevOps 用 MS SQL Server 存引用,Cursor 选择 WAL + S3。区别在于:WAL 不依赖外部数据库,每个仓库的完整历史状态都在 WAL 里——可以回放、可以 rewind、可以 fast-forward。S3 的持久性(11 个 9)和可用性(CAS 原子操作)让 Git 数据的强一致性有了天然的底层保障。

第三,这是 Cursor 继 Origin 之后的第二张底牌。 Origin 是产品层(代码托管 UI、API、Agent 接口),Continuity 是基础设施层(存储引擎、复制协议、可用性保障)。两层合在一起,Cursor 不只是做一个「GitHub 替代品」,是在重写 Git 托管的地基。

第四,对比全行业。 GitHub 用 Spokes 跑了 13 年,Azure DevOps 用 blob + SQL,Google 用 JGit + DHT(已放弃)。Cursor 的 Continuity 是目前公开方案中最新的设计——WAL + S3 + 无共识 + 随意副本数。它能不能在生产环境稳定跑,还需要时间验证,但设计思路的清晰度在同类系统中无出其右。

文章作者 Vicent Martí 的前 mentor 是 Shawn Pearce——Google JGit + DHT 方案的实现者。这个传承关系本身就是一段历史:师父试过路线三失败了,徒弟在路线二的基础上重构出了新方案。

对了,顺带一提:Cursor 在 8 月 14 日被 SpaceX 收购了。所以 Origin 和 Continuity 不只是产品发布,更像是被收编前的技术底牌亮牌。

参考文档与链接

你用过 Origin 了吗?对比 GitHub/GitLab 体验如何?评论区聊聊。觉得有用点个赞让更多人看到。


作者: itech001 来源: 公众号:AI人工智能时代 网站: https://www.theaiera.cn/ 每日分享最前沿的AI新闻资讯和技术研究。

本文首发于 AI人工智能时代,转载请注明出处。

分享给朋友