每秒 7000 万次请求。这个量级如果挂在推理服务上,人们会点点头说「合理」;挂在一个存储平台上,就有点不讲道理了。OpenAI 官方博客开了一个系列,第一篇讲的就是这套叫 Habitat 的在线存储平台——它扛着每周超过 10 亿用户的 ChatGPT,管着 500PB 以上的数据,铺在近 40 个地区。更有意思的是它的履历:一个从 Python 小库长出来的系统,最后被重写成了 Rust 服务。
一个 Python 库,怎么被十亿人踩上去
Habitat 的出身相当平民。官方在系列上篇里承认,它最初就是一个内部用的 Python 库,职责简单到可以用一句话讲完:给上层应用一个统一的地方存文件、取文件、查文件在哪。当时没人会预判,几年之后这个库要面对每周十亿级的用户量。
起点小得可怜
早期做存储,写的其实是接口。把文件塞进对象存储、把路径和元信息写进数据库、给业务方一个干净的 API——这三件事用 Python 拼起来,几天就能跑通。跑通和跑得住之间,隔着十万八千里。真正的分水岭出现在需求侧:模型要保存对话,用户要上传图片和文档,多模态的输入形态一个接一个冒出来,写请求从「偶尔一次」变成了「时时刻刻」。一个为内部工具设计的抽象,开始被公开流量反复捶打。
重写这件事,拖得越久越贵
什么时候该换语言?答案从来不是性能数字,而是你手里还有多少余量去改架构。Habitat 靠异步和水平扩展这两根拐杖,撑过了很长一段时间。等到单机吞吐、内存占用、GC 停顿这些指标开始互相打架,团队才意识到问题已经不是调参能解决的了。Rust 版重写不是为了跑分,是为了重新拿回对内存布局、并发模型和错误处理的控制权。拖得越久,要迁移的历史包袱就越厚。
asyncio 的账,最后还得还
官方把 asyncio 的调优经验单独拎出来讲,这一点很实在。事件循环只有一个,任何一段同步代码都能把它堵死;线程池大小、DNS 解析、序列化这些看起来边角的地方,在高并发下全是主角。连接池尤其如此——池子开小了排队,开大了把下游数据库按倒,这条线没有教科书答案,只能靠真实流量一点点试出来。异步带来的复杂度不会消失,它只是被推迟到了你最不想面对的深夜。
Habitat 真正管的是「谁存在哪」
很多人以为存储平台的核心是硬盘。错得离谱。这类系统最难的活是元数据:哪个文件存在哪个容器、属于谁、什么时候过期、副本落在哪几个机房。字节可以扔给对象存储,元数据的读写却必须又快又准,一毫秒都省不下来。
字节和目录,是两回事
把大块二进制丢给对象存储,成本低、扩展性好,基本是行业共识。难的是在那之上叠一层目录语义。一次上传要写几行元数据,一次列举要扫一批索引,一次删除要确保不留悬空指针。每秒 7000 万次请求里,绝大多数并不在搬字节,而是在回答「这个文件在哪」。这也解释了为什么元数据层往往比数据层更早撞墙。
连接池不是配置项,是生存线
数据库连接是稀缺资源。Habitat 服务着近 40 个地区、成千上万个租户,如果每个请求都去抢连接,下游会被瞬间打穿。连接池在这里的角色更像调度器:控并发、排队、超时、快速失败。官方愿意花篇幅讲这一层,说明它在真实事故里交过学费。
分片之后,麻烦才刚开始
数据量到了 500PB 这个级别,单库单表早就没有讨论价值。分片是必然选择,但分片键选错,热点立刻跟着来。更麻烦的是跨片操作:一次批量删除可能横跨多个分片,一个事务边界可能落在两台机器上。分布式系统的复杂度不会消失,它只会从代码里转移到运维和故障处理里。
7000 万 QPS 的代价清单
7000 万 QPS、500PB、40 个地区,这三个数字放在一起,说明 Habitat 已经不是内部工具,而是一层基础设施。基础设施的评判标准只有一个:出问题的时候,别人还能不能继续干活。
长尾延迟比峰值更致命
平均值好看毫无意义。P99 和 P999 才是用户能感知到的东西:图片转圈、对话卡住、上传失败。存储层的长尾通常来自几个固定源头——慢查询、锁竞争、跨区网络抖动、GC。对付长尾的办法也朴素:超时、降级、缓存、把慢路径拆出去单独处理。
40 个地区,意味着 40 倍的失败模式
多地域部署听起来像扩张,实际是放大。每个地区有独立的容量曲线、独立的网络质量、独立的合规要求。一次区域级的对象存储抖动,会在上层变成一连串看似无关的报错。Habitat 要做的是把这些差异封装掉,让业务方看到的始终是一个稳定接口,而不是一张世界地图。
规模变了,架构的形状也得变
从百万到千万再到七千万,量变会逼出质变。早期有效的缓存策略会失效,早期能接受的锁粒度会变成瓶颈,早期够用的日志会淹没整个磁盘。Habitat 的演进史,本质上是一遍遍把「够用」改成「扛得住」。
这套经验,别的团队能搬走多少
把 OpenAI 的规模照搬到自己公司毫无意义。但路径上的几个判断,是可以复用的。
换语言之前,先定位瓶颈
如果瓶颈在数据库,换语言只会让你更快地把数据库打挂。Habitat 改 Rust 的前提,是它已经清楚自己卡在运行时而不是存储引擎上。顺序搞反了,重写就是一场几百万行代码的赌博。
分层思路比选型更值钱
对象存储放字节、元数据服务放索引、缓存扛热点——这套分层不绑定任何厂商。不少团队栽跟头,恰恰是因为把元数据塞进了对象存储,或者把大文件塞进了关系型数据库。Habitat 的规模很极端,但它做的权衡一点也不新鲜。十亿用户踩过的系统,最后沉淀下来的不是某个 Rust crate,而是「什么时候该分层、什么时候该重写」的判断力。这个系列还没写完,Habitat 的故事也远没到结尾。

