OpenAI如何在没有分片的情况下,用一个主库支持8亿用户的PostgreSQL

每当有大公司的基础设施相关文章发布时,Hacker News 上总会出现一堆评论,内容大多是这样的变体:“当然了,他们用Kubernetes撑起了47个微服务,还加了一套自主开发的分布式共识协议数据库。”然而,当真相是他们只是用单纯的PostgreSQL主库和一点使用规范支撑其业务时,评论区就会陷入一片尴尬的沉默。 这次,OpenAI就再次打了这样一个大脸。 超出所有人想象的数字 OpenAI基础设施工程师Bohan Zhang刚刚分享了他们如何用PostgreSQL支持ChatGPT的具体细节。令人惊讶的数据如下: 8亿用户 单一PostgreSQL主库(写入操作专用)部署在Azure上 ~50个只读副本 每秒百万次查询 p99延迟仅10-19毫秒 99.999%的可用性 一年内仅出现一次SEV-0事故 (而且还是因为ImageGen产品的病毒式传播,让一周之内新增了1亿用户) 再读一遍。一个。主库。支撑8亿用户。 “可是他们为什么不分片?” 不需要。背后的原因非常简单而务实。 给PostgreSQL分片需要改动数百个应用的端点。每一个默认假设所有数据都在同一个数据库查询——基本是所有查询——都需要重写,来判断每个数据属于哪个分片。 这么迁移需要付出的成本呢?是数月的工作量、新的bug层出不穷,再加上一个混乱的迁移过渡期——同时需要维护老旧和新系统。 于是他们采用了另一种方式:识别最占用写入负载的数据,然后将其移至Cosmos DB。而这样做的原因并不是因为Cosmos比PostgreSQL更好,而是因为这些特定的工作负载更适合文档数据库模型。而其他大部分业务逻辑依旧保留在PostgreSQL中。 用大白话说:他们没有让整个系统变复杂,而是精确识别出问题所在,并有针对性地解决它。精密手术刀式的调整,而不是拿电锯一通乱砍。 PgBouncer:将连接延迟从50毫秒降到5毫秒 他们遇到的第一大瓶颈是建立连接的延迟。PostgreSQL会为每个新连接创建一个独立进程。而随着来自成百上千个应用Pods的并发连接数增加,光是处理新连接的开销就已达到50毫秒——甚至还没开始执行查询呢。 他们的解决方案是:使用PgBouncer作为连接池。PgBouncer会维护一个已经建立好的连接池,复用这些连接。结果是连接延迟从50毫秒降至5毫秒,直接减少了90%的延迟。仅仅通过更换一项底层工具,问题就得到了解决。 值得提到的是,这根本不是什么新技术。PgBouncer已经有15年以上的历史,并一直被各种规模的企业用于生产环境中。然而,它再次证明,一款久经考验的不起眼的工具,解决了这个地球上使用最频繁应用之一的问题。 那个做了12个表联接的ORM 这个问题是我的最爱。我见过它出现在学生的项目、初创公司,甚至银行的系统里。到处都有。 他们的ORM生成了包含12个表联合查询(join)的SQL语句。罪魁祸首并不是哪个设计人员,而是因为数据模型过于复杂且关系交织,ORM顺着这些关系“不假思索”地将每个可能的相关表都加载了进来。 解决办法既不是换ORM,也不是手动改写所有的查询。他们选择了将一些逻辑转移到应用层。与其让PostgreSQL执行一个庞大的join操作,他们分拆成多个简单查询,然后用代码对数据进行整合。 这么做优雅吗?的确没那么优雅。速度快吗?快得多。因为PostgreSQL处理简单查询比处理含有交叉条件的12表联合查询高效得多。而且,部分结果还能进行缓存和复用。 1 2 3 4 5 6 7 8 9 10 11 12 13 -- 之前:ORM生成的SQL SELECT u.*, p.*, s.*, t.*, ... FROM users u JOIN profiles p ON ... JOIN settings s ON ... JOIN teams t ON ... JOIN ... -- 总计12个表 WHERE u.id = $1; -- 之后:语句被拆分,逻辑移到应用层 SELECT * FROM users WHERE id = $1; SELECT * FROM profiles WHERE user_id = $1; -- 可缓存、可并行、可调试 每一条单独的查询都很简单。查询解析器几微秒内就可以完成。并且一旦其中有一条失败或者变慢,你可以直接找到问题所在。 ...

2026年3月11日 · Fernando