当业务规模从百万级跃升至亿级时,数据库扩展往往被视为一道难以逾越的鸿沟。传统观点认为,单一 PostgreSQL 实例难以支撑如此巨大的流量,水平分片几乎是必经之路。然而,OpenAI 的工程实践打破了这一认知:在过去一年间,其 PostgreSQL 负载增长超过十倍,却依然凭借单主节点加近五十个跨地域读副本的架构,支撑着八百万 ChatGPT 用户的百万级查询每秒吞吐量,同时保持低十位数毫秒的 p99 延迟和五个九的可用性。这一成绩的取得并非依赖运气,而是源于一系列经过严格验证的工程优化策略。
架构选择:读流量全卸载,写流量外部化
OpenAI 的 PostgreSQL 架构核心思想简洁而务实:最大限度降低主节点的负载压力,使其始终保有充足的余量应对突发流量。具体而言,所有读流量都被路由至读副本,只有必须与写事务捆绑的查询才留在主节点执行。这一策略的关键前提是 ChatGPT 的工作负载具有极强的读密集特性 —— 用户发起对话、获取历史记录、加载界面元素等操作绝大多数都是只读查询,写入操作主要集中在新消息保存、用户状态更新等相对低频的场景。
对于无法避免的写流量,OpenAI 采取了更为激进的策略:将可分片的写密集型工作负载迁移至 Azure Cosmos DB 等分布式系统。这意味着并非简单地在 PostgreSQL 内部进行优化,而是从架构层面将不适合单节点处理的负载剥离出去。剩下的写入操作往往是那些难以分片但量级可控的业务逻辑,它们仍然由 PostgreSQL 主节点处理,但通过应用层优化减少不必要的写入次数,例如修复导致重复写入的应用程序缺陷、引入延迟写入机制以平滑流量峰值、在进行大规模数据回填时严格限制写入速率等。
这种架构选择背后有着深刻的工程考量。PostgreSQL 的多版本并发控制实现对写密集型工作负载并不友好:当更新一行数据时,整个行会被复制以创建新版本,导致显著的写放大;同时,查询时需要扫描多个元组版本才能获取最新数据,增加读放大。在高写入压力下,还会引发表和索引膨胀、索引维护开销上升、autovacuum 调优复杂等一系列连锁问题。因此,与其强行在 PostgreSQL 内部解决这些问题,不如将这类负载迁移至专为高写入场景设计的分布式数据库。
连接池与查询优化:夯实扩展根基
即便架构设计再精良,如果连接管理和查询执行效率低下,系统仍然会在压力下崩溃。OpenAI 在这一层面投入了大量精力,其中最具代表性的举措是部署 PgBouncer 作为数据库代理层。PgBouncer 运行在语句模式或事务模式下,能够高效复用数据库连接,极大降低活跃客户端连接数。实测数据显示,平均连接建立时间从五十毫秒降至五毫秒,降幅达十倍。这一优化不仅提升了响应速度,更显著降低了连接资源耗尽的风险。
在查询层面,OpenAI 的经验是必须对复杂 JOIN 操作保持高度警惕。他们曾发现一个涉及十二张表关联的查询在流量高峰期消耗大量 CPU,成为多次高严重性故障的罪魁祸首。解决方案是尽量避免在数据库层面进行复杂的多表关联,将这类逻辑移至应用层处理。对于必须保留的 JOIN 操作,需要仔细审查对象关系映射框架生成的 SQL,确保其行为符合预期。此外,配置如 idle_in_transaction_session_timeout 等超时参数对于防止长事务阻塞 autovacuum 至关重要。
连接数本身也是一个硬性约束。Azure PostgreSQL 的单实例最大连接数为五千,在高并发场景下极易耗尽。PgBouncer 的连接池机制是解决这一问题的主要手段,但配置必须谨慎,特别是空闲超时等参数需要精细调优。另一个值得关注的优化点是地域延迟:跨地域连接开销显著,因此应将代理层、应用程序和副本部署在同一地域,最大程度减少网络往返时间和连接占用时长。
缓存击穿防护与流量整形
数据库层的优化固然重要,但缓存层的设计同样关乎整体系统的稳定性。OpenAI 使用缓存层承载大部分读流量,这在正常情况下能够有效保护数据库。然而,当缓存命中率意外下降时,大量请求会瞬间涌入数据库,形成缓存击穿风暴,瞬间耗尽 CPU 和连接资源。OpenAI 的解决方案是实现缓存锁机制:当多个请求在同一缓存键上发生缓存未命中时,只有最先获得锁的请求被允许访问数据库以重新填充缓存,其他请求则等待缓存更新完成而非同时冲击数据库。这一机制将冗余的数据库读取请求压缩至最小,显著降低了突发流量对数据库的压力。
流量整形是另一个关键环节。OpenAI 在应用层、连接池、代理层和查询层多个维度实施了速率限制,防止突发流量压垮数据库实例。更为重要的是,合理的重试间隔设计能够避免重试风暴 —— 当请求失败时,过短的重试间隔会导致大量重试请求同时涌向数据库,加剧故障。他们还在对象关系映射层增加了速率限制支持,在必要时可以完全阻断特定的查询摘要,这是应对异常流量波峰的快速恢复手段。
级联复制与高可用保障
当读副本数量接近五十个时,一个被忽视的问题开始显现:主节点需要向每个副本流式传输预写日志数据。随着副本数量增加,主节点的网络带宽和 CPU 压力持续上升,导致复制延迟波动加剧,系统的水平扩展能力受到制约。OpenAI 正在与 Azure 团队合作推进级联复制的实现,使中间副本能够将预写日志中继至下游副本,而非所有副本都直接连接主节点。这一方案有望在不对主节点造成额外压力的情况下,将副本数量扩展至上百个。当然,级联复制也带来了更复杂的故障转移管理问题,需要确保在各种异常场景下都能安全切换。
高可用设计同样精益求精。主节点以高可用模式运行,配备一个热备副本始终保持同步,可在主节点故障或需要维护时快速接管。虽然写操作仍然需要主节点,但读操作可以在主节点完全不可用的情况下继续提供服务,显著降低了单点故障的影响范围。每个地域部署多个副本并预留充足的容量冗余,确保单个副本故障不会导致地域级服务中断。
变更管控与容量规划
数据库变更管理是容易被低估的风险点。即便看似微小的 Schema 变更,例如修改列类型,也可能触发整表重写,在大表上造成灾难性影响。OpenAI 的策略是严格限制仅允许轻量级 Schema 变更,例如添加或删除不触发表重写的列。所有 Schema 变更强制执行五秒超时,创建和删除索引必须使用并发模式。新增表的需求被引导至 Azure Cosmos DB 等分片系统而非 PostgreSQL。当需要进行大规模数据回填时,即便耗时可能超过一周,也必须严格限制写入速率以避免生产环境受到影响。
这些严格的变更管控措施背后是惨痛的教训。在过去十二个月中,OpenAI 仅发生一次 SEV-0 级别的 PostgreSQL 事故,恰好发生在 ChatGPT ImageGen 功能发布期间 —— 一周内新增超过一亿用户,写流量瞬间激增十倍。这一案例既说明了流量突增的破坏力,也证明了经过充分优化的架构在面对极端场景时仍能保持弹性。
工程启示
OpenAI 的实践表明,在读密集型工作负载下,PostgreSQL 可以通过精细的工程优化支撑远超预期的规模。关键不在于使用多么前沿的技术,而在于深刻理解系统瓶颈并针对性地逐一化解:连接池解决连接数瓶颈,读副本解决读吞吐瓶颈,缓存层解决数据库负载波动,级联复制解决副本扩展瓶颈,写流量外迁解决主节点写入瓶颈。这些优化措施相互配合,共同构建了一个稳定、高效、可扩展的数据层。
当然,这一路径并非放之四海而皆准。OpenAI 的工作负载具有读远多于写的特点,且其团队拥有深厚的数据库工程能力。对于读比例较低、查询复杂度更高或团队数据库经验有限的组织,单纯依靠优化单节点 PostgreSQL 可能并非最优解。但无论如何,OpenAI 的经验提供了一条值得参考的扩展路径,也为那些认为「上亿用户必须分片」的传统观念提供了有力的反例。
参考资料
- OpenAI Engineering Blog: "Scaling PostgreSQL to power 800 million ChatGPT users" (2026 年 1 月 22 日)