AREX Feed Article
OpenAI 详解 ChatGPT 存储架构:联手 Azure Cosmos DB,称全球中位读延迟从约 120ms 降至约 10ms
北京时间 10 月 24 日凌晨,OpenAI 面向开发者的官方 X 账号 @OpenAIDevs 发布一组帖子,,并称其以毫秒级速度向 40 个地理区域的超过 12 亿用户提供数据——为达到这一规模,OpenAI 与 Azure Cosmos DB 团队密切合作设计存储架构,全球中位读延迟(global median read latency)获得 12 倍改善。
数字来自随帖附上的工程博客——10 月 23 日发布的《Rapidly scaling online storage to serve over 1 billion ChatGPT users (Part II)》,署名作者是 Jon Lee、Hrachya Hakobyan 和 Chaomin Yu 三位技术成员(Members of Technical Staff)。的口径更具体:自今年年初开始聚焦性能以来,三项设计改动把全球读请求 p50(第 50 百分位)延迟从约 120ms 压到约 10ms。这套存储属于 OpenAI 的在线存储平台 Habitat——按 9 月 11 日发布的,Habitat 在 2023 年 DevDay 上以 Python 客户端库的形态支持 GPTs 首次上线,如今每秒处理超过 7,000 万次请求,支撑每周超过 10 亿人使用的产品,数据量超过 500 PB。文中的规模与性能数字均出自 OpenAI 自己的帖子和博客,未经独立核实。
三项改动:复制认证元数据,缓存高频数据,重写服务层
按博客的次序:先做到可靠,再做到够快,最后才是大规模下的运营效率。2025 年系统趋稳、OpenAI 向全球扩张之后,延迟成了下一个约束。把改善拆成三项做法,博客正文逐一展开。
第一项是复制的取舍。广域复制只留给小型、关键、每个请求都需要的数据集,典型是认证元数据。做法是用带大量次要区域的高度复制 Cosmos DB 账户缩短计算与数据之间的往返:部分账户复制到 OpenAI 服务的全部 40 个 Azure 区域,另一些至少覆盖每个大洲一个区域。博客同时写明,这条路受容量约束,只能用于少数手工挑选的数据集;为此他们比原计划更早给 Habitat 加了一层透明的数据搬迁与路由层,用来在不同复制拓扑的账户之间移动数据。
第二项是缓存。读请求占 Habitat 流量的 90% 以上,其中不成比例的份额来自一个相对小的高频工作集——设置、应用状态这类反复读取的属性。Habitat 内置了分布式旁路缓存(lookaside cache),把最近访问的对象和边放在靠近请求处理位置的 Valkey 服务器上。失效是难点:TTL(缓存条目存活时间)短了削弱缓存收益,长了则长期供应陈旧数据。OpenAI 的做法是借 Cosmos DB 的 change feed(变更流)做变更数据捕获(CDC),由专门服务消费变更流、对各区域本地缓存执行失效,让失效在全球秒级传播——博客称这一设计参照了 Meta 的 TAO 系统。承载失效传播的 CDC 平台每秒捕获数百万条变更,经 100 多个 Kafka 主题供给二级索引、数据搬迁管道和离线分析;OpenAI 还修改了 Azure CDC SDK 的检查点实现,改为在内存中批量暂存、定期刷写,以提高效率。
第三项是重写:Habitat 服务层从 Python 改用 Rust,称由此降低了代理开销(proxy overhead);博客补了一句,Rust 比原先的 Python 性能更好。
容器策略三次摇摆:从共享到隔离,再回到共享
多租户是博客的另一条主线。Habitat 的底层容器走过一条环形路线:从默认共享一个 Cosmos DB 容器,到给关键用例单开容器,最后回到默认共享,与 Azure 团队共同做出一套「共管容器」(co-managed containers)方案。
最早的单容器模式撞上三类问题。不同产品在 user_id、workspace_id 等常用逻辑分区键上频繁碰撞,共享每键 10,000 RU/s(每秒请求单位)的文档上限;物理分区上的「嘈杂邻居」让小众功能的负载拖累核心登录与注册流程;分区随数据增长而分裂,容器总吞吐被摊到更多分区上,每个分区的实际吞吐反而缩水。
改用独立容器换来隔离,却失去多租户的稳定聚合增长。博客算了一笔账:在共享容器里,一个新用例从 0 冲到每秒 100 万请求几乎不动全局水位;在独立容器上,这可能是内部测试基线的 1,000 倍。产品团队因此必须在发布前预扩容,而他们经常忘——OpenAI 写道,发布日大家坐在事故处理室里临时扩容器的场面反复出现,容量规划实际上扩散到了每个产品团队。
最终方案回到共享容器,由两家联合补齐隔离手段:对最热的键先限流;给批量插入、数据导出等离线负载分配更低的 QoS(服务质量)优先级,拥塞时先压它们;Azure Cosmos DB 团队还为 OpenAI 构建了新的 serverless(无服务器)模式——每个物理分区可扩到 10,000 RU/s,并在按存储量分裂之外增加按 RU 用量分裂。博客称,切换之后数月内没有再发生容量供给或嘈杂邻居事故,产品团队基本不再需要做前期或持续的容量规划;推文里对应的那句总结是:产品团队要管理的基础设施更少,所以推进更快。
2024 年底的两次故障,促成 OpenAI 与 Azure 的联合运维
OpenAI 在博客里说,到了一定规模,托管服务就不再「托管」。他们自称已是 Azure Cosmos DB 最大的用户之一:最大的账户存着数十 PB 数据、每秒处理超过 2,000 万次请求,并称据其所知是唯一在这个规模上部署 Cosmos DB 的公司。
促成这种合作模式的是两次真实事故。2024 年底,OpenAI 一个最大的 Cosmos DB 账户所在的 Azure 主区域断电;随后的故障转移演练让双方发现,这个体量的账户切到次要区域要花数个小时——两家都没在自己的规模上测试过这件事。约一个月后把账户切回原区域时,又触发一次严重事故:原区域的 Cosmos DB 网关被连接风暴压垮,网关(gateway)模式客户端处理故障转移时的一个怪癖,让所有客户端立即重连并发送请求,尽管当时只有一部分物理分区迁了回去。两次事故中双方各自走完事故处理流程,定位了多处根因并部署修复。
如今两家共同监控 Habitat 从服务层到 Cosmos DB 物理存储的每一层,在等比生产规模的非生产账户上演练变更,一起测试 SDK(软件开发工具包),通过 Teams 直接沟通,甚至可以绕过支持层级直接呼叫(page)对方。过去一年的联合工作包括改进 Cosmos DB 控制面与网关的扩展性、在网关侧加元数据缓存与负载保护、用连接池提高 Python 服务进程的连接复用率、尽可能同置工作负载,以及用不同 VPC(虚拟私有云)把关键负载与离线负载隔开。
容量设限:数据放不进想放的区域
把数据放在用户附近可以直接降低延迟。OpenAI 为有数据驻留(data residency)合规要求的用户,在不同 Azure 区域单独维护 Cosmos DB 账户。但博客承认,这个思路推广不开:数据集体量太大,很多区域装不下与其用户流量份额相称的存储足迹。
在机房容量、电力或散热紧张的区域,团队面对一道直接的取舍:把容量留给同置存储换取低延迟,还是拿它做服务计算、把存储请求路由到更远的地方。放置决策因此成为产品层面的权衡——一边是不同产品与用户子集的延迟,一边是原始的存储与算力容量。受此约束,广泛复制只覆盖少数数据集;对其余数据,博客的做法是靠缓存把跨区域延迟「藏」进区域内。
尚未回答的 p99,和为「下一个十亿用户」自建的系统
帖子发布当天,在回复中写道:「性能、规模与运维简洁并不总是同时到来。这是一个三者兼得的不错例子。」回复区里,多位开发者的追问指向另一个指标:「这个规模下的 p99(第 99 百分位)读延迟是多少,毕竟中位数会好看得多」,也有人「中位数是最讨好的指标,你的 12 亿用户感受到的是 p99」,并顺带问这个规模的账单长什么样。
博客承认:缓存大幅压低的是中位延迟,最慢的请求仍要从底层存储取未缓存数据,而且常常要跨遥远的区域。OpenAI 给出的下一步分两条:随着容量上线、存储效率改善,从源头把数据放在将被访问的地方;以及一套仍在开发中的自研存储系统——为「下一个十亿用户」扩展 Habitat 与会话存储,结合 Rockset 的 RocksDB Cloud 内核与基于 Raft 的复制,实现与 Azure Cosmos DB 相同的文档模型,用分离式存储加物理复制省下闪存容量,代价是较低的峰值 QPS(每秒查询数)。两个答案都还没有时间表:博客没有公布 p99 数字,自研系统也仍标注为开发中。