Anthropic 的 Scion 设计对数据意味着什么

lakeFS 2026-10-24T09:35:27.641088

2026 年 5 月,Anthropic 每天要合并大约 2,500 个代码改动。到了 9 月,这个数字涨到 3 万以上。增长主要来自 agent(智能体),而在这个过程中,git 慢慢跟不上了。于是他们换掉了 git。介绍新方案 Scion 的那篇文章,是我今年读过的系统设计类文章里写得相当好的作品之一。

文章讲的是一个代码 monorepo(单体仓库)的源码管理。里面专门有一节讲数据结构,但这里说的“数据”是 Scion 自己的:变更集、派生索引,以及存放在云存储里的文件内容。数据集版本管理并不在讨论范围内。

不过,文章里的很多决定,对做过数据版本控制的人来说都很眼熟。真正有意思的地方,是我们做了相反选择的那两处。

先直接回答标题的问题:Scion 的存储设计,和数据版本管理本来就绕不开的做法很接近,因为数据从一开始就不可能全塞进一台笔记本里。数据的不同之处,在于一次糟糕变更之后会发生什么。而一旦写操作交给 agent 来做,这种差别就会改变你对分支和合并的理解方式。

Scion 改掉了什么

Git 假设每个客户端都持有一份完整、可离线使用的仓库副本。Anthropic 的客户端几乎全是 agent 和 CI 任务,永远在线,所以他们干脆放弃了这个假设。由此带来几点变化:

存储层看着很眼熟

Scion 切换分支的方式是:“在 Spanner 单行上做一次 compare-and-swap(比较并交换)。”元数据和 ref 存在 Spanner 里,文件内容存在云存储里。

lakeFS 切换分支的方式则是:分支是一个指向某次提交的指针,存放在键值存储里(DynamoDB 或 PostgreSQL)。

提交时用比较并设置(compare-and-set)机制:开始时读取分支状态,结束时只有中间没有任何变化才更新分支。提交元数据以内容寻址文件的形式和数据放在同一个对象存储里,写入后就不再修改。lakeFS 服务器把常用的元数据缓存在本地磁盘和内存中。名字不同,形状一样。一个小的、强一致的存储保存少量会变化的状态。其余全部不可变,放在廉价存储上,任何节点都能直接缓存,不用问任何人。我觉得这里不存在谁抄谁。说到底,这种设计是被现实逼出来的。一旦客户端永远在线且数量众多,全量克隆就划不来了。对代码来说,每天 3 万次合并才让这件事成真。对数据来说,从第一天起就是如此。没人会把 400 TB 的训练集克隆到自己的笔记本上,对吧?我们走了另一条路:快照。Scion 的工作单元是变更集(changeset),它“存储相对于第一个父提交发生变更的文件列表”。相比之下,git 提交“存储的是指向树的指针”。Scion 随后在服务器上构建派生结构,以便快速回答历史和追责查询。lakeFS 的提交更接近 git 那一侧。每个提交指向一个 metarange,也就是由 range 构成的两级默克尔树的根,这棵树描述了该提交时仓库的完整状态。未变化的 range 在提交之间共享,所以一次提交的成本大致等于变更内容的大小。读取任意历史提交的完整状态是一次查找,而不是重建。对数据来说,我认为这是正确的取舍。人们问数据的问题通常是“这个模型到底在什么数据上训练的”。而这个问题往往在六个月后才被提起。当读取历史状态是主要访问模式时,你希望这种读取足够便宜。我们走了另一条路:分支。这是更大的差异。Scion 可以劝退使用 refs,并跳过全局合并锁,因为改坏代码的代价很低,撤销很容易。

这篇文章说得很直接:“并发变更可能产生冲突,但 Claude 通常能比人类更快地修复这些冲突,快到人类甚至还没发现它们。”其余的靠合并后和部署前的测试兜底。现在想象一个智能体在整理数据仓库。它判断 customers_final_v2_DO_NOT_USE 是 customers 的重复表,于是把两张表合并,过程中丢掉了 40% 的行。如果你的检查在合并之后才跑,那你只能在合并之后才发现问题。到那时,夜间的训练任务已经读过这张表,某个仪表盘已经刷新过,另一个智能体已经用它构建了一个客户分群。回滚这张表并不能让模型“忘记”它训练过的东西。代码可以从源码重新构建,数据却会被下一个读取它的东西消费掉。所以对数据来说,分支才是安全机制。每一次智能体运行都拿到自己的分支,在 lakeFS 里这是一个零拷贝指针,所以创建一个分支几乎不花什么成本。智能体往这个分支里写。检查以合并前钩子的形式跑在这个分支上,在任何一个字节进入 main 之前。如果检查失败,分支直接丢弃,生产环境根本没见过它。如果还是有东西溜了进去,main 可以回退到上一个提交。Scion 把 ref 数量压到最低,因为在它们的规模下协调 ref 很贵。我们接受更多的 ref,因为对数据而言,一个隔离的分支是智能体犯错成本最低的地方。

如果你在数据上跑智能体,能从 Scion 学到什么

你大概率不需要造一个 Scion 这样的东西。对大多数团队来说,即便是大型企业团队,Git 用于代码就足够了。Anthropic 自己也这么说:“我们在这里概述的概念,只对真正巨大的 monorepo 才有意义。”但我仍然会关注这个方向,不是因为你的代码,而是因为你的数据。往你数据里写的智能体数量在增加,这会以更大的方式影响你和你的团队。有几条思路可以直接借鉴:

对于代码,合并后再处理通常没问题。但对于数据,隔离必须在合并前完成,这意味着每个写入者要有一个独立分支,并在该分支上运行检查。记录每次 agent 运行的 commit ID。没有这个记录,当有人问 agent 到底看到了什么时,你基本是在盲飞。同样的特性也体现在读性能上。lakeFS 的 commit 永不改变,因此客户端可以缓存它,无需反复检查元数据。这也是为什么在我们的 MLPerf Storage 测试中,lakeFS Mount 在热读场景下比 Mountpoint for Amazon S3 快约 57%。完整的 Scion 文章值得一读,尤其是关于 fetch 协议和分层缓存的部分。如果你想更深入了解 lakeFS 这一侧,internals 文档会带你走一遍 Merkle 树和分支更新路径。文章 What Anthropic’s Scion design means for data 首发于 lakeFS。

2026年5月,Anthropic 每天合并约 2,500 个代码变更。到9月,这个数字超过了 30,000。大部分增长来自智能体(agent),而在这个过程中,git 渐渐跟不上了。于是他们换掉了 git。描述这个替代方案 Scion 的文章,是我读过的系统类写作中比较好的一篇 […] 文章《What Anthropic's Scion design means for data》首发于 lakeFS。

查看原文