扩展在线存储服务超过10亿ChatGPT用户(下)

Habitat 是 OpenAI 的在线存储平台,为所有 OpenAI 产品提供毫秒级数据访问,服务超过 10 亿用户、横跨 40 个地理区域,存储量超过 500 PB。本文是系列第二部分,聚焦底层组件 Azure Cosmos DB 的扩展过程,以及 OpenAI 与 Azure 团队如何通过共同管理让多租户架构在全球规模下变得可靠。

最初 OpenAI 依赖 Azure Cosmos DB 内置原语,使用默认的单个多租户容器,依靠每个逻辑分区键 10K RU/s 的限制提供背压。这种方式暴露出三类问题:逻辑分区键被客户端直接选择,导致 user_id、workspace_id 等热门键在不同业务间频繁碰撞,共享限额;物理分区才是实际限流单位,逻辑分区无法真正达到 10K RU/s,同一物理分区上的噪声邻居会拖垮无关的关键链路;物理分区随数据增长不断分裂,而总吞吐不变,导致每个分区的有效吞吐上限随数据体积增大而收缩。此前在 Postgres 扩展中,一个热组织或热键的请求就可能打垮整个数据库,团队曾为此做了大量缓存和租约工作。

为缓解这些问题,第二阶段开始对最关键的新用例使用独立容器,实现工作负载隔离,并用脚本同步容器总吞吐与物理分区数,规避弱分区。这确实缩小了爆炸半径,避免了不少站点级故障。但独立容器让每个新用例从 0 到 1M QPS 的增长变成千倍级负载变化,失去了多租户聚合增长的平滑效应。团队经常上线时忘记预置吞吐,容量规划变成每个产品团队都需要深度参与的负担,组织上无法持续。

于是第三阶段回到多租户默认,并与 Azure 团队联合开发共享租户修复方案:热键节流优先限制最热键,阻止噪声邻居耗尽物理分区吞吐;QoS 请求分级让离线工作负载(批量插入、数据抽取)先被节流,保护交互请求;Azure Cosmos DB 团队还提供了改进的 serverless 模式,允许每个物理分区扩展到 10K RU/s,并支持基于 RU 使用量的拆分,不再需要人工监控分区和手动扩容。切换后,产品团队几乎无需预先容量规划,几个月内没有出现容量预置或噪声邻居事故。

当 OpenAI 成为 Azure Cosmos DB 最大用户之一后,托管服务不再是单纯托管。最大的账户存储数十 PB 数据,服务超过 20M QPS。据 OpenAI 称,他们是唯一在 Azure Cosmos DB 上达到该规模的公司。2024 年底的区域停电和一个月后的回切故障,暴露了故障转移耗时数小时、连接踩踏冲击网关等问题。双方随后建立了联合监控、生产规模非生产测试账号、SDK 共同迭代、直接工程师沟通和互相 paging 的机制,并对控制面、网关可扩展性、连接池、VPC 隔离等做了大量改进。

性能方面,计算和存储容量经常不在同一区域,跨区域请求不可避免。Habitat 的读取占请求超过 90%,优化策略分为三层:在物理容量允许时把数据放在用户附近;仅对最小且最延迟敏感的数据集(如认证元数据)做广泛复制,有些账户复制到全部 40 个 Azure 区域;对其余数据依赖集成分布式缓存,使用 Valkey 服务器放在用户请求处理附近,并通过 Azure Cosmos DB change feed 驱动的 CDC 在数秒内全局失效,避免 TTL 的命中率/新鲜度权衡。此外,用 Rust 重写了 Habitat 服务,降低代理开销。这些改动将全局读 p50 从约 120 ms 降到约 10 ms,12 倍提升。

CDC 本身也被扩展为平台能力:每秒数百万变化、数千容器、数百万分区,通过 100 多个 Kafka topics 服务次级索引、数据移动、离线分析和实时产品功能。内部控制面持续分配工作、选择读取区域、管理数千 worker。团队还改进了 Azure 的 CDC SDK,在内存中批量检查点并定期刷新,并用死信队列防止永久性投递失败阻塞后续数据。

展望方面,为复制到下一个十亿用户规模,OpenAI 正在自研 exabyte 级在线存储系统,针对 Habitat 的大数据块类型优化。该系统结合 Rockset 的 RocksDB Cloud 核心与 Raft 复制,实现与 Azure Cosmos DB 相同的文档模型,但使用分离式存储和物理复制来减少闪存需求,以降低峰值 QPS 为代价。

Rapidly scaling online storage to serve over 1 billion ChatGPT users (Part II)

查看原文