#PostgreSQL 作为功能强大的开源关系型数据库,常被认为更适合中小规模业务场景。近日 #OpenAI 的一篇博文 将 PostgreSQL 扩展至支持 8 亿 #ChatGPT 用户,说明凭借合理的架构设计、精细的性能优化和坚实的工程落地,PostgreSQL 完全能够应对超大规模的生产负载,尤其是在读密集型场景中具备超出预期的扩展潜力。从 OpenAI 的实践中,我们可以借鉴哪些经验呢?
构建分层体系,隔离数据库风险
好的应用架构体系一定是分层的,OpenAI 构建了以数据库为中心的“连接池+缓存+数据库”的三层架构。
代理层
数据库支持的连接数有限,短时间频繁登录数据库带来的连接风暴会给数据库带来巨大的压力,甚至影响正常的对外服务。为此 OpenAI 采用 #PgBouncer 作为代理层来实现数据库连接池,大幅减少活跃客户端连接数,将平均连接时间从数十毫秒降至毫秒;同时将 PgBouncer、客户端和只读副本同区域部署,有效减少跨区域网络的开销和连接占用时间。
缓存
缓存是减轻数据库读压力的关键,将高频度、低频更新的数据放入缓存层,承接 90%以上的读流量,从根本上减少数据库的读请求。
为了防止“缓存未命中风暴”,OpenAI 创新的实现了缓存锁定机制:当多个请求同时未命中同一缓存键时,仅允许一个请求前往数据库获取数据并回填缓存,其他请求等待缓存更新。即使在缓存被击穿时,也能有效的杜绝大量请求同时涌向数据库,避免数据库 CPU 饱和。

数据库副本
数据库层又分为主数据库和副本两个层次组成,其中:
主库采用分片机制将数据写入到不同的子集,有效弥补了 PostgreSQL 密集写入能力上的不足; 副本则用于支持读类型的应用,OpenAI 也实现一套严格的查询管控机制,减轻海量查询对于主库的压力。
这部分内容接下来会展开说,这里不再赘述。
分布式数据分片,应对高写入负载
和很多迅速发展状态的初创公司一样,OpenAI 在应用需求急剧增长的时候也在数据库上遇到了不小的挑战。PostgreSQL 的 MVCC 机制使得其在高写入负载下会导致显著的写入放大,查询时必须扫描多个元祖版本以获得最新数据,又会导致读取放大,这些缺陷使得 PG 在处理这类应用时效率比较低下。
为了减轻写入压力,OpenAI 选择了 #Azure Cosmos DB,这是一款完全托管在 Azure 公有云,支持 NoSQL、关系型和向量等多种数据类型的分布式数据库,能够提供个位数毫秒级的响应时间,具备自动实时扩展能力。

分布式的好处是可以基于分片将数据拆分成多个子集,将水平分区友好的写入密集型业务迁移至分片系统,从根源上减少数据库的写入量,是应对数据库瓶颈的法宝。
读写分离,支持每秒数百万次查询
为了支持海量的查询需求,OpenAI 在全球多个地理区域运行了近 50 个读副本。当前架构还不支持级联日志同步,所有的 WAL 都是通过主库传输到副本的。为此 OpenAI 联合 Azure PostgreSQL 团队合作开发级联复制方案(架构上类似于 Oracle Far Sync),一旦这个架构成功实现,再也不用担心无限制的添加副本会压垮主库了。

超大规模场景下,少数高开销的查询就可能耗尽数据库资源,引发服务中断。基于读写分离架构,OpenAI 建立了多方面的查询管控机制,从源头规避低效查询带来的风险。
对应用请求进行分级,分别路由到专用的数据库实例,防止某个产品流量的波动影响其他业务的稳定性; 建立严格的读写分离规则,除写事务关联的读查询之外,所有的读请求全部路由至只读副本,通过自动化工具监控主库读请求占比,及时发现并调整违规的查询路由; 尽可能避免多表连接查询,尤其杜绝超过 3 张表的关联查询。如果必须要这样做的,则将连接逻辑拆分到应用层处理,通过应用聚合数据替代数据库层的关联查询; ORM 框架容易生成低效 SQL,建立 SQL 审查机制,对 ORM 生成的查询语句进行全量校验,发现低效 SQL 语句后及时优化。
写在最后
PostgreSQL 经常被贴上“仅适配中小规模业务”的标签,OpenAI 却用支撑 8 亿 ChatGPT 用户的实践来证明,精妙的设计和工程实现,能够大大提升数据库的性能上限。
面对高写入负载带来的放大效应,拆分业务迁移至分布式分片系统;面对副本扩张压垮主库的风险,联合厂商制定开发级联复制方案;面对低效查询可能引发的服务中断,建立审查和分级路由管控机制。通过主动的架构设计来规避数据库自身能力的不足,能够满足业务需求的系统就是优秀的系统!
这些经验对于我们改造国产数据库能带来哪些启发呢,欢迎大家留言讨论!




