postgresql是openai核心产品的关键底层数据库,通过单主+近50个只读副本架构支撑每秒数百万次查询和8亿用户;其读扩展能力强,但写入受限于mvcc机制,故将可分片写负载迁移至cosmos db,并持续优化查询、负载分流与高可用方案。

多年来,PostgreSQL 始终是支撑 ChatGPT 与 OpenAI API 等核心产品的关键底层数据系统。随着用户基数的迅猛增长,数据库面临的需求也呈指数级攀升。过去一年中,我们的 PostgreSQL 负载增长了逾 10 倍,且增势不减。
在不断升级生产基础设施以支持业务增长的过程中,我们有一项关键发现:PostgreSQL 支撑读密集型负载的潜力远超想象,其扩展能力比许多人预想的更为强大。这个最初由加州大学伯克利分校团队创建的系统,使我们能够凭借单个 Azure PostgreSQL 灵活服务器主实例(在新窗口中打开),以及遍布全球多个区域的近 50 个只读副本,成功应对海量的全球流量。本文将讲述 OpenAI 技术团队如何通过严谨的优化和坚实的工程实践,将 PostgreSQL 扩展至每秒处理数百万次查询、服务 8 亿用户,并分享这一过程中积累的关键经验。
初始架构的隐忧
ChatGPT 发布后,流量以前所未有的速度激增。为此,我们在应用层与 PostgreSQL 数据库层快速实施了全面优化,既通过提升实例规格进行纵向扩展,也通过增加只读副本来横向扩展。这套架构在很长一段时间内都运行良好。持续的改进也为其未来的增长预留了充足空间。
单主架构竟能满足 OpenAI 的规模需求,或许令人意外,但其实际落地绝非易事。我们曾遭遇多次因 PostgreSQL 过载引发的严重事件(SEV),其模式往往相似:上游问题(如缓存层故障导致的大范围缓存穿透、消耗大量 CPU 的复杂多表连接查询激增,或新功能上线引发的“写入风暴”)导致数据库负载骤增。随着资源利用率攀升,查询延迟上升,请求开始超时。后续涌入的重试流量会进一步推高负载,这可能引发一个自我强化的恶性循环,最终导致 ChatGPT 与 API 服务性能严重劣化。
尽管 PostgreSQL 对我们的读密集型工作负载扩展性良好,但在高写入流量期间,我们仍面临挑战。这很大程度上源于 PostgreSQL 的多版本并发控制(MVCC)实现机制,使其在处理写入密集型负载时效率较低。例如,当一个查询更新一个元组甚至单个字段时,整行数据都会被复制以创建新版本。在高写入负载下,这会导致显著的写入放大。同时,由于查询必须扫描多个元组版本(死元组)以获取最新数据,这也增加了读取放大。MVCC 还带来了表与索引膨胀、索引维护开销增加以及自动清理调优复杂等额外挑战。
将 PostgreSQL 扩展至每秒数百万次查询
为缓解上述限制、减轻写入压力,我们已经并将继续把可分片的写入密集型工作负载(即可水平分区的工作负载)迁移至 Azure Cosmos DB 等分片系统,并优化应用逻辑以尽可能减少不必要的写入。同时,我们也不再允许在当前的 PostgreSQL 部署中添加新表。新的工作负载默认使用分片系统。
即便基础设施持续演进,PostgreSQL 仍保持未分片状态,由单个主实例处理所有写入。主要考量在于,对现有应用工作负载进行分片将极其复杂且耗时,需修改数百个应用端点,可能耗费数月甚至数年。鉴于我们的工作负载以读为主,且已实施大量优化,当前架构仍有充足余量支持流量持续增长。虽然不排除未来对 PostgreSQL 进行分片的可能性,但考虑到当前及未来的增长空间充裕,这并非近期优先事项。
下文将深入探讨我们面临的挑战,以及为防止未来服务中断、将 PostgreSQL 推向极限并扩展至每秒数百万次查询(QPS)所实施的一系列深度优化。
为主库负载减负
挑战:单一写入节点意味着单主架构无法横向扩展写入能力。剧烈的写入峰值可能迅速压垮主库,进而影响 ChatGPT 及 API 等服务。
ChatGPT Atlas(macOS)可在浏览网页时提供即时回复、内容总结与任务辅助。它支持智能建议、信息整理及多场景交互,同时配备可控隐私设置,让用户在使用过程中更加安全安心。针对 macOS 平台优化后,带来流畅自然的浏览体验,适用于办公、学习、创作及日常信息查询等多种场景。
解决方案:我们尽最大努力减少主库负载(包括读和写),以确保其有足够容量应对写入峰值。读取流量尽可能被分流至副本。然而,部分读查询因其属于写事务的一部分而必须留在主库执行,对此我们着力确保其高效并避免慢查询。对于写入流量,我们已将可分片的写入密集型负载迁移至 Azure Cosmos DB 等分片系统。更难分片但仍产生高写入量的负载迁移耗时更长,目前仍在进行中。我们还积极优化应用以减少写入负载,例如:修复导致冗余写入的应用 Bug;在适当场景引入延迟写入以平滑流量峰值。此外,在回填表字段时,我们会强制执行严格的速率限制,以防产生过度的写入压力。
查询优化
挑战:我们识别出 PostgreSQL 中一些高开销查询。过去,这类查询的流量一旦激增,便会大量挤占 CPU 资源,导致 ChatGPT 和 API 服务出现延迟。
解决方案:少数几个高开销查询(例如涉及多表连接的查询)就可能导致整个服务严重劣化甚至中断。我们需要持续优化 PostgreSQL 查询,确保其高效并避免常见的 OLTP 反模式。例如,我们曾定位到一个连接了 12 张表的极高开销查询,其流量峰值是过去几次高严重性 SEV 事件的元凶。我们应尽可能避免复杂的多表连接。如果必须连接,我们学会考虑将查询拆分,并将复杂的连接逻辑移至应用层处理。许多有问题的查询由对象关系映射(ORM)框架生成,因此仔细审查其生成的 SQL 并确保其符合预期至关重要。PostgreSQL 中也常出现长时间运行的空闲查询,配置 idle_in_transaction_session_timeout 等超时参数对于防止其阻塞自动清理至关重要。
缓解单点故障
挑战:若某个读副本故障,流量可被路由至其他副本。但依赖单一写入节点意味着存在单点故障 — 一旦它宕机,整个服务将受影响。
解决方案:大多数关键请求仅涉及读查询。为缓解主库的单点故障风险,我们将这些读查询从主库卸载至副本,确保即使主库宕机,这些请求仍可继续服务。虽然写操作会失败,但影响面已缩小,不再构成最高级别(SEV-0)事故。
为减轻主库故障影响,我们以高可用(HA)模式运行主库,并配备一个热备副本(持续同步、随时可接管流量的副本)。当主库宕机或需下线维护时,我们能快速提升备用副本,最大限度减少停机时间。Azure PostgreSQL 团队已做了大量工作,确保即使在极高负载下,这些故障转移也能安全可靠。为应对读副本故障,我们在每个区域部署多个副本,并预留充足的容量余量,确保单个副本故障不会导致区域性服务中断。
工作负载隔离
挑战:我们常遇到某些请求在 PostgreSQL 实例上消耗不成比例资源的情况,导致同一实例上其他工作负载性能下降。例如,新功能上线可能引入低效查询,大量消耗 PostgreSQL CPU,拖慢其他关键功能的请求。
解决方案:我们在全球多个地理区域运行了近 50 个读副本以尽可能减小延迟。然而在当前架构下,主库必须向每个副本流式传输 WAL。尽管目前通过使用超大型实例类型和高网络带宽尚能良好扩展,但我们无法无限制地添加副本而不最终压垮主库。为此,我们正与 Azure PostgreSQL 团队合作开发级联复制方案(在新窗口中打开),即由中间副本将 WAL 中继给下游副本。此方法使我们有望扩展到上百个副本,而不会令主库不堪重负。但这也会引入额外的运维复杂性,尤其是在故障转移管理方面。该功能仍在测试中;我们将在确保其健壮且能安全故障转移后,再将其推向生产环境。










