OpenAI 官方博客于近日正式发文,详细阐述了其如何将 PostgreSQL 扩展至现有规模:采用一套包含单一主库及近50个只读副本的超大型集群,支撑其核心产品(ChatGPT 与 OpenAI API)的全球流量。
与半年前在 PGCon.Dev 上的分享(《OpenAI:将PostgreSQL伸缩至新阶段》相比,本次官方博文披露了几个关键变化:副本数量从“一主40从”增加了约10个;用户规模也从5亿跃升至8亿,增长势头迅猛。更重要的是,在单集群写入吞吐接近天花板后,他们选择将可水平分片的写密集型负载迁移至 Azure Cosmos DB(基于 PostgreSQL + Citus 的路线),而非走传统的“应用层手动分片”老路。
这为 PostgreSQL 提供了一个极为稀缺的、由风口公司打造的标杆级生产案例。过去虽有不少公司依赖 PostgreSQL 支撑至上市或被收购(如 Instagram、探探),但像 OpenAI 这样对全行业产生溢出效应的案例,确实少见。本文对官方文章进行了编译,并依原文顺序附上技术解读。

伸缩 PostgreSQL,支撑 8 亿 ChatGPT 用户
原文地址:https://openai.com/index/scaling-postgresql/
多年来,PostgreSQL 一直是支撑 OpenAI 核心产品(如 ChatGPT 和 OpenAI API)最关键、最底层的数据库系统。随着用户量激增,数据库面临的负载压力也呈指数级攀升。过去一年,我们的 PostgreSQL 负载增长了 10 倍以上,且仍在快速上升。
在升级生产基础设施以承载增长的过程中,我们获得了一个新认知:PostgreSQL 在读多写少的场景下,所能可靠扩展到的规模远超许多人的想象。这套最初由加州大学伯克利分校科学家打造的系统,如今我们仅用 一台主库(Azure PostgreSQL 灵活服务器实例)配合 近 50 个分布在全球多个区域的只读副本,就支撑起了海量的全球访问。本文将分享 OpenAI 如何通过严谨的优化与扎实的工程手段,将 PostgreSQL 扩展到支撑 8 亿用户、每秒数百万次查询(QPS),并总结一路走来的关键经验。
初始设计开始出现裂缝
ChatGPT 上线后,流量以前所未有的速度增长。为应对压力,我们在应用层和数据库层都进行了大量优化:一方面通过提升实例规格进行“纵向扩展”,另一方面持续增加只读副本来“横向扩展”。这套架构在很长时间内表现良好,并且通过持续改进,仍为未来增长预留了相当的空间。
听起来可能有些反直觉:单主架构 竟能满足 OpenAI 这种量级的需求。但要在现实中稳定运行它,并不容易。我们经历过多次由 PostgreSQL 过载引发的高级别事故,它们通常遵循相似的路径:上游某处故障导致数据库负载骤增——例如缓存层失效造成大范围缓存未命中;某些昂贵多表 JOIN 查询激增打满 CPU;或新功能上线引发“写入风暴”。当资源占用持续走高,查询延迟开始上升,请求陆续超时;紧接着,重试机制会进一步放大负载,形成恶性循环,最终可能拖慢甚至拖垮整个 ChatGPT 与 API 服务。

尽管 PostgreSQL 对我们的“读多写少”负载扩展性良好,但在写入流量很高的时段,我们仍会遇到挑战。主要根源在于 PostgreSQL 的多版本并发控制实现,使其在写密集负载下效率并不理想。例如,一次更新操作即使只修改一行中的一个字段,也会复制整行来生成一个新版本。在高写入压力下,这会导致显著的 写放大。同时伴随 读放大:查询为获取最新版本,需要扫描多个行版本(包括“死元组”)。MVCC 还会引发一系列额外问题,如表与索引膨胀、索引维护开销增加以及 autovacuum 调参的复杂性。(关于这些问题,可参考深度文章:The Part of PostgreSQL We Hate the Most。此文也曾被 PostgreSQL 维基词条引用。)
将 PostgreSQL 扩展到百万级 QPS
为了绕过这些限制、降低写入压力,我们已经并将持续把那些 可分片的写密集型工作负载 迁移到如 Azure Cosmos DB 这样的分片系统中;同时也在优化应用逻辑,尽量减少非必要写入。并且,我们不再允许在当前的 PostgreSQL 部署中新增表——新业务默认直接使用分片系统。
尽管基础设施持续演进,PostgreSQL 本身仍保持未分片:所有写入仍由 单一主库实例 承担。主要原因在于,对现有应用负载进行分片将极其复杂且耗时,需要修改数百个应用端点,周期可能长达数月甚至数年。考虑到我们的负载以读为主,且已进行了大量优化,现有架构仍有充足余量承接增长。我们并不排除未来对 PostgreSQL 进行分片的可能性,但短期内这不是优先事项——就当前及可预见的增长而言,我们的“跑道”足够长。
接下来,我们将展开说明遇到了哪些挑战,以及实施了哪些大规模优化来解决它们、避免未来故障——从而将 PostgreSQL 推向极限,最终扩展到每秒数百万次查询。
降低主库负载
挑战:只有一个写入节点时,单主架构无法横向扩展写入。写入流量突增很容易压垮主库,进而影响 ChatGPT 和 API 等服务。
解决方案:我们尽可能将主库压力降至最低——包括读和写——确保主库永远留有足够余量应对写入突增。能路由到副本的读请求,尽量下沉到副本。但有些读查询因处于写事务中必须留在主库,我们重点确保这些查询足够高效。写入方面,已将可分片的写密集负载迁移至 Azure CosmosDB 等分片系统。更难分片但写入量仍高的负载,迁移周期更长,正在进行中。同时,我们也对应用进行了更激进的优化以降低写负载:例如修复导致重复写入的 Bug;在合适场景引入“延迟写”以平滑流量尖峰。此外,在对表字段进行回填时,我们会施加严格的速率限制。
查询优化
挑战:我们在 PostgreSQL 中识别出多条高开销查询。过去,这些查询一旦出现调用量激增,就会消耗大量 CPU,拖慢 ChatGPT 和 API 的请求。
解决方案:少数几条昂贵查询——尤其是涉及多表 JOIN 的查询——就足以显著降低性能甚至拖垮服务。我们必须持续优化 PostgreSQL 查询,确保其高效,并规避常见的 OLTP 反模式。例如,我们曾发现一条极其昂贵的查询 JOIN 了 12 张表,其流量突增曾直接触发多次高级别事故。能不做复杂多表 JOIN 就尽量不做;如果确实需要,我们学会了考虑拆分查询,将复杂 JOIN 逻辑移至应用层处理。许多问题查询来自 ORM 框架自动生成,因此必须认真审查 ORM 产生的 SQL。另一个常见问题是 PostgreSQL 中存在长时间空闲但仍占用事务的查询;配置类似 idle_in_transaction_session_timeout 这样的超时参数至关重要,否则它们会阻塞 autovacuum。
缓解单点故障
挑战:读副本故障,流量可切至其他副本;但仅依赖单一写入节点意味着存在单点——主库一旦故障,整个服务都会受影响。
解决方案:大多数关键请求只涉及读操作。为降低主库单点故障的影响,我们将这些读请求从主库下沉到副本,确保即便主库宕机,这些请求仍能继续服务。虽然写操作会失败,但整体影响被显著缩小:因为读服务仍然可用,这就不再是最高级别的事故。
针对主库故障,我们以高可用模式运行主库,并配置一台持续同步的热备副本,随时准备接管。当主库宕机或需下线维护时,可快速提升热备,最大限度缩短停机时间。Azure PostgreSQL 团队做了大量工作,确保即便在极高负载下,此类故障转移仍安全可靠。针对读副本故障,我们在每个区域部署多个副本并预留足够余量,确保单个副本故障不会演变为区域级故障。
工作负载隔离
挑战:我们经常遇到某些请求在 PostgreSQL 实例上消耗不成比例的资源,导致同实例上的其他负载性能下降。例如新功能上线带来的低效查询疯狂消耗 CPU,从而让其他关键功能变慢。
解决方案:为缓解“吵闹邻居”问题,我们将不同负载隔离到专用实例,避免资源密集型请求的突增影响其他流量。具体做法是将请求拆分为低优先级与高优先级两个层级,并路由到不同实例。这样即便低优先级负载突然变得资源密集,也不会拖慢高优先级请求。我们在不同产品与服务间也采用同样策略,避免某个产品的活动影响另一个产品的性能与可靠性。
连接池
挑战:每个实例都有最大连接数上限(Azure PostgreSQL 为 5,000)。连接很容易被打满,或积累大量空闲连接。我们曾因“连接风暴”耗尽所有可用连接而引发事故。
解决方案:我们部署了 PgBouncer 作为代理层实现连接池。以语句级或事务级连接池模式运行,它可以高效复用连接,大幅减少活跃的客户端连接数。同时也能降低建立连接的开销:在我们的基准测试中,平均建连时间从 50 毫秒降至 5 毫秒。跨区域连接和请求成本高昂,因此我们将代理、客户端和副本尽量部署在同一区域,以降低网络开销并缩短连接占用时间。此外,必须谨慎配置 PgBouncer,例如空闲超时等参数对避免连接耗尽至关重要。

每个读副本都有其独立的 Kubernetes 部署,运行多个 PgBouncer Pod。我们在同一个 Kubernetes Service 后面运行多个 Deployment,由 Service 在各个 Pod 之间进行负载均衡。
缓存
挑战:缓存未命中率突然飙升,会导致 PostgreSQL 读取请求暴涨,CPU 被打满,用户请求变慢。
解决方案:为降低 PostgreSQL 的读压力,我们使用缓存层承接绝大多数读流量。但当缓存命中率意外下降时,大量未命中请求会直接涌向数据库。读取请求的骤增会消耗大量资源,拖慢服务。为在“缓存未命中风暴”期间防止系统过载,我们实现了缓存锁(以及租约)机制:对同一个 key,只有一个 未命中请求会去 PostgreSQL 拉取数据。当多个请求同时未命中同一个缓存 key 时,只有一个请求拿到锁并负责回源、回填缓存;其他请求等待缓存更新,而不是同时冲击数据库。这能显著减少重复的数据库读取,避免负载尖峰被层层放大。
扩展只读副本规模
挑战:主库需要将预写日志流式发送给每一个读副本。副本数量越多,主库要发送 WAL 的目标就越多,网络带宽和 CPU 压力都会上升,导致副本延迟更高、波动更大,使系统更难稳定扩展。
解决方案:我们在多个地理区域运营近 50 个读副本以降低延迟。但在当前架构下,主库必须向每个副本推送 WAL。虽然依靠超大规格实例和高带宽网络,目前运行良好,但副本数量不可能无限增长——迟早会将主库推至极限。为此,我们正与 Azure PostgreSQL 团队合作测试 级联复制:由中间副本将 WAL 转发给下游副本。这样可以在不压垮主库的前提下,将副本规模扩展到上百个。但它也会引入更多运维复杂度,尤其是在故障切换管理方面。目前该功能仍在测试;投产前,我们会确保其足够健壮,并能安全完成故障转移。

限流
挑战:某些端点流量突增、昂贵查询激增或重试风暴,可能迅速耗尽 CPU、I/O、连接等关键资源,进而引发大范围性能劣化。
解决方案:我们在多层实施限流——应用层、连接池层、代理层、查询层——避免流量尖峰将数据库实例压垮并触发级联故障。同时必须避免过短的重试间隔,防止形成重试风暴。我们还增强了 ORM 层以支持限流;必要时可以直接 彻底阻断 某些特定的查询摘要。这种“定点卸载负载”的方式能在昂贵查询突然暴涨时快速止血,帮助系统迅速恢复。
Schema 管理
挑战:即便是很小的 schema 变更,比如修改某列类型,也可能触发一次 全表重写。因此我们对 schema 变更极其谨慎:只允许轻量操作,避免任何会重写整表的变更。
解决方案:只允许不会触发全表重写的轻量变更,例如添加或删除非关键列。我们对 schema 变更强制 5 秒超时。允许并发创建/删除索引。Schema 变更仅限于已有表;如果新功能需要新增表,就必须放到 Azure CosmosDB 等替代的分片系统中,而不是继续塞进 PostgreSQL。在进行字段回填时,我们同样施加严格限速,防止写入突增。虽然这个过程有时可能超过一周,但能换来稳定性,并避免对生产造成影响。
结果与下一步
本次实践表明:只要设计得当、优化到位,Azure PostgreSQL 完全可以扩展以承载超大规模的生产级工作负载。对于读多写少的场景,PostgreSQL 能以百万级 QPS 运行,为 OpenAI 最核心的产品提供支撑。我们增加了近 50 个读副本,同时将复制延迟保持在接近零的水平;在全球分布的区域维持了低延迟读取;并预留了足够的容量余量,为未来增长做好准备。
在尽量不牺牲延迟的前提下,这套扩展方案也显著提升了可靠性。我们在生产中稳定提供 p99 客户端延迟为“两位数毫秒级”,可用性达到“五个9”(99.999%)。过去 12 个月里,我们仅发生过一次最高级别的 PostgreSQL 事故(发生在 ChatGPT ImageGen 的一次病毒式发布期间:写入流量突然暴涨 10 倍以上,一周内新增用户超 1 亿)。
我们对 PostgreSQL 目前的表现感到满意,但仍会继续将其推向极限,确保为未来增长留足跑道。我们已经将那些可分片的写密集负载迁移到了 CosmosDB 等分片系统。剩余的写密集负载更难分片——我们也在持续推进迁移,以进一步将写入从 PostgreSQL 主库上卸载。同时,我们还在与 Azure 合作推动级联复制落地,确保可以安全地扩展到更多读副本。
展望未来,随着基础设施需求持续增长,我们也会继续评估更多扩展路线,包括对 PostgreSQL 本身进行分片,或采用其他分布式系统。
技术解读
七年前,我在探探维护过一套当时可能是国内规模最大的 PostgreSQL 集群——总体 250 万数据库 QPS,最大的核心单集群为一主32从,承载大几十万 QPS。我亲历了从“单集群打天下”到垂直拆分、再到水平分片与微服务改造的全过程。OpenAI 文中描述的很多问题,我们当年都遇到过。下面按原文脉络,聊几个观察点。

单机写入的真实天花板
互联网业务的读写比通常非常极端,10:1 乃至几十比一并不罕见。只读查询理论上几乎没有“硬天花板”:机器不够就加副本,物理复制或级联复制能把读扩展得很漂亮。真正困难的是单机写入:如果写入速率超过单台 PostgreSQL 的承载能力,就不得不走向分库分片。
在现代硬件上,单机 PostgreSQL 的写入瓶颈往往体现为 WAL 写入速率、事务吞吐以及背后存储的持续写能力上限。你可以通过更强的 CPU、更快的 NVMe、更大的内存把这条线推高,但它终究存在,一旦触及就必须进行结构性拆分。
作为经验参考,单机 PostgreSQL 的写入瓶颈通常在 100-200 MB/s 的 WAL 速率,或者每秒 100-200 万次点写入事务。OpenAI 这篇文章的价值之一,是用一个极强的现实样本阐明:对于接近十亿用户量的应用,核心业务仍然可以在相当长时间里维持“单主 + 大规模只读副本”的架构而不立即分片。
MVCC 膨胀的利弊权衡
文中提到的文章讨论了 PostgreSQL MVCC 的代价:写放大、表膨胀、VACUUM、FREEZE 等。这些问题客观存在,但工程的核心在于“利弊权衡”。PostgreSQL 的 MVCC 设计固然有其开销,但带来的好处也是实实在在的:极低的复制延迟与稳定的流复制提高了可靠性;读写互不阻塞极大提高了并发吞吐;可回滚的大事务为复杂分析提供可能。表膨胀等问题本质上是 可工程化治理 的,关键在于你愿意为这些好处支付怎样的运维成本。
该分片还是得分片
OpenAI 在文章中提到,尽管写入已接近瓶颈,但仍保持 PostgreSQL 本身不分片。不过他们冻结了这套集群的新增业务,转而使用 Azure Cosmos DB。CosmosDB for PostgreSQL 实质上是 PostgreSQL + Citus,因此在增量部分实质上已采用了分片方案。
我们最初也是一套数据库集群支撑所有业务,然后垂直拆分成20套独立集群。但仍有几个核心业务无法支撑,于是参照类似 Instagram 的 PostgreSQL 水平分片架构,搭建了一套分片集群,最终扩展到64个分片。当时我们也有一套 Citus 集群,但彼时其部分关键运维功能尚未开源,加上运维管理复杂,最终下线。如今这些问题大多已解决,若今天要进行 PostgreSQL 分片,Citus 会是值得重点考虑的选择。
主库优化:数据重力考验工程能力
由于 OpenAI 选择对现有集群不分片,这意味着必须将单主库的性能榨取到极限,这涉及大量精细的工程技巧:写入治理、慢查询优化、连接风暴防控、缓存雪崩应对、DDL 变更纪律、限流熔断、快慢分离等——每一项展开都不神秘,但正是这些细节体现了真正的工程能力。
此外,一套高负载的主库在管理上需要许多精细化操作。一些在小库上可以随意执行的 ALTER TABLE 或全表 UPDATE,在生产集群上必须慎之又慎。不过近年来,PostgreSQL 在这方面改进良多,许多 DDL 操作已可在线快速完成。总的来说,管理超高负载的 PostgreSQL 主库虽然挑战依旧,但工具和生态已比几年前成熟许多。
关于 ORM
看来 OpenAI 已在 ORM 上踩过坑。ORM 经常生成糟糕的嵌套 SQL,对于追求极致性能的场景可能是一种“负优化”。那么,如何在保留便利性的同时生成可靠、稳定的 SQL 呢?我们当时使用过一个叫 sqlc 的工具,它能根据数据库模式自动生成 Go 语言结构体及增删改查方法,确保 SQL 是静态、稳定且高度可预测的。
关于高可用与级联复制
文中显示是“主库直挂近 50 个副本”。这既说明了 PostgreSQL 足够健壮,也意味着主库承担了可观的 walsender、网络与 CPU 压力。在七年前的硬件与网络条件下,一台主库拖带超过10个从库就会产生显著影响,因此我们会强制采用级联复制:主库只直连一部分“桥接副本”,更多只读副本挂在桥接副本之下。
OpenAI 测试级联复制的方向是正确的。但级联复制真正的难点不在于“能否转发”,而在于故障切换后的拓扑重建与自动化运维流程。这部分若处理不好,级联反而会放大运维复杂度。
关于工作负载隔离
当集群负载上去后,“快慢分离”是一项重要工作,OpenAI 显然已遇到了“吵闹邻居”问题。当“在线查询”与“离线分析查询”混合时,会产生各种性能干扰。
因此,在设计集群架构时,除了主库、从库这两种经典角色,我们还引入了“离线实例”角色。离线实例专门用于承载长事务、ETL 工作流以及数据分析师查询等“准在线”业务,避免它们影响核心在线业务。

快慢分离的另一面是“快查询”的优化。对于互联网场景,绝大多数点查询都可受益于缓存。但有趣的是,在达到相当规模之前,我们甚至没有引入缓存,直接用 PostgreSQL 硬扛——事实上它也扛下来了。这对开发者的一个启发是:或许不必过早引入缓存使架构复杂化。
关于连接池
连接池依然是提升 PostgreSQL 高并发性能的关键组件,而 PgBouncer 至今仍是优选之一。它提供事务级池化能力,性能极致,并能作为额外的监控与流量管控点。
PgBouncer 的事务连接池有化腐朽为神奇的效果。例如,将几千条客户端连接、数万 QPS 通过池化收敛到少数几条数据库连接,能极大减少数据库进程间的资源竞争。其美中不足在于它是单进程应用,在极高负载下可能打满单核 CPU,但可以通过部署多个实例来解决。OpenAI 将 PgBouncer 部署在应用侧是可行的方式,但需要研发侧配合。
总结
决定数据库选型胜负的三要素常被认为是:技术套件、标杆案例、生态系统。
在生态系统上,PostgreSQL 已占据主导地位,而 OpenAI 则提供了一个强有力的 标杆案例。我们所做的,正是尝试将生产级 PostgreSQL 所需的技术套件——涵盖高可用架构、备份恢复、监控运维等——做成可复制、可普及的解决方案,把“能支撑到 OpenAI 这个量级之前都用得上”的能力,下放给更多团队。
OpenAI 的案例再次证明,绝大多数企业并不需要追逐花哨的数据库“大观园”,扎扎实实地用好一套 PostgreSQL,就足以支撑业务走向相当远的未来。对于希望深入探讨 PostgreSQL 及其他后端技术的开发者,欢迎到 云栈社区 交流分享。
参考资料
[1]: https://www.pgevents.ca/events/pgconfdev2025/schedule/session/433-scaling-postgres-to-the-next-level-at-openai/
[2]: https://openai.com/index/scaling-postgresql/
[3] Azure PostgreSQL 灵活服务器实例: https://learn.microsoft.com/en-us/azure/postgresql/overview
[4] The Part of PostgreSQL We Hate the Most: https://www.cs.cmu.edu/~pavlo/blog/2023/04/the-part-of-postgresql-we-hate-the-most.html
[5] cited: _https://en.wikipedia.org/wiki/PostgreSQL#cite_note-37_
[6] 级联复制: https://www.postgresql.org/docs/current/warm-standby.html#CASCADING-REPLICATION
[7] 全表重写: https://www.crunchydata.com/blog/when-does-alter-table-require-a-rewrite
[8] 病毒式发布: https://newsletter.pragmaticengineer.com/p/chatgpt-images