暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL百万多租户架构设计

原创 梧桐 2025-06-21
215

在SaaS 世界里,多租户(multi-tenant)架构几乎是默认选择。每个租户都是一个客户,其数据需要隔离、安全、可扩展、易于迁移。然而,PostgreSQL数据库从来不是为支撑百万租户而生的。那么,能不能把 PostgreSQL 重新深化一下,以更好地支持多租户呢?
我们看看Nile的作法,,提出了这样一个问题,并且带来了他们的解法。她一步步地把“租户”这个概念注入 PostgreSQL 的核心运行逻辑中,从元数据、数据隔离,到执行计划,再到数据迁移,每层面都以“租户”为关注核心。

为何 PostgreSQL 难以自然支持多租户?

当前,PostgreSQL多租户架构主要依赖Schema或(和)租户ID的使用, 表面看起来简单易用,但在实际扩展中,尤其当租户数量从几百跃升至几十万、甚至上百万时,PostgreSQL 开始露出它“单租户优化”的本质。例如常见的数据组织模型——**隔离模型**和**共享模型**。隔离模型以每个租户一个数据库或 schema 的方式保证隔离性,共享模型则将所有数据放入共享表中,以租户 ID 区分。虽然隔离模型更安全、更灵活,但资源开销巨大;共享模型虽然节省资源,却很难应对租户之间突发的负载变化或性能争抢。因此,在真正大规模的场景下,两种模型都难以完美适配。
问题在于,PostgreSQL 没有内建任何“租户意识”。它不知道表里有哪些租户,也无法针对某个租户做局部的优化操作,更别提单租户备份或迁移了。而这正是 Nile 团队解决的核心点。

让 PostgreSQL “理解”租户

Nile 的基本策略是,把“租户”从一个隐藏在业务表主键里的普通列,变成系统级别的概念。他们**把 PostgreSQL 的每个租户,视为一个“逻辑数据库”**,并构建出一套支持百万租户的高效调度体系。
架构设计上,**每个租户的数据被组织在专属的 tablespace 和表中**。例如,租户 456 的数据会在 `events_456`、`users_456` 这类表中。这些表不仅属于某个租户专有的表空间,也可以被单独调度至某个 serverless compute 节点上,实现弹性伸缩。
与传统的“一个数据库一个租户”相比,Nile 实现了**逻辑隔离**而非物理隔离,避免了资源浪费,同时保留了管理的灵活性。每个租户都像是被映射到了一张虚拟的数据库视图之中,而实际的数据结构是高度模块化、可组合的。


解决表数量与性能的困局

即便逻辑清晰,技术上也有不少坑等着踩。最典型的问题,是 PostgreSQL 对于分区数量的承载能力极其有限。虽然 PostgreSQL 的分区表支持按照租户 ID 建表,但一旦超过几千分区,catalog cache 的膨胀和查询计划器的延迟就开始令人无法接受。
Nile 团队的解决方案,是**将结构拆成“父表 + FDW(外部表) + 局部分区”的混合模型**。通过 FDW(Foreign Data Wrapper)和自定义的存储路径,每个 serverless compute 节点只管理少数租户的分区,而非全量表。这种方式降低了元数据负载,同时也允许并行查询和租户间的横向扩展。

可以理解为,打造一个租户感知的元数据库层,把 PostgreSQL 的单体能力转化为“租户驱动的分布式执行”。


查询和 DML 如何适配?


值得注意的是,在传统共享表模型中,查询语句往往要靠应用层自动注入 `WHERE tenant_id=xxx` 条件,既繁琐又容易出错。而在 Nile 模型中,**查询的入口是一个租户路由器**——Nile Gateway。无论是查询(SELECT),还是插入/更新(INSERT/UPDATE),Gateway 都会自动将 SQL 路由至对应的真实表,甚至重写语句,将其指向 `events_456` 或其他具体结构。

这种方式对上层应用来说几乎是透明的,而对底层存储系统来说,每次操作都是一个精确命中的局部更新,性能和安全性都得到大幅提升。

为什么“可迁移性”是关键?

传统架构下,要把某个租户从一个数据库节点迁移到另一个,往往需要全表导出、停机维护甚至 DNS 切换,代价高昂。而 Nile 把**迁移过程模块化:先冻结租户表中的数据,然后将对应 WAL(写前日志)切片存入共享存储,最后在新位置重建元数据并重新挂载这些分区**。整个过程对租户而言几乎无感。
这意味着:系统可以在负载不均时快速“搬家”,某个客户也可以根据地理位置合规要求被动态地部署到特定区域,而不会影响系统整体结构。

更多创新设计


值得强调的是,Nile 并不是简单用 PostgreSQL 加些插件和外部服务。而是在 PostgreSQL 源码级别进行了多处 patch:
- 允许扩展模块接管 `smgr`(storage manager);
- 增加 `tablespace` 的元信息与回调能力;
- 改进 CREATE TABLE 的继承语法,支持物理布局拷贝;
- 修改系统 catalog 支持 UUID 类型和租户层级逻辑。
可以说,他们用 PostgreSQL 盖出了一栋符合当代 SaaS 需求的全新大厦。

一个“懂租户”的 PostgreSQL,才是 SaaS 的未来


一个现实问题:当你要为上百万个客户服务时,如果数据库不能“懂得”租户的存在,那每一个优化都只能靠应用补锅,难以为继。
Nile不只是让 PostgreSQL 支持多租户,而是让多租户成为 PostgreSQL 的核心构造元素。在这样一个架构中,隔离性、弹性、性能、成本控制、合规性——这些原本互相矛盾的目标,第一次被有机整合在了一起。
这不是一次轻巧的封装,而是一次深度的工程再造。而这样的再造,或许也预示着未来 PostgreSQL 向“云原生数据库”演进的一个方向。


《Scaling Postgres for Millions of Tenants》Gwen Shapira Nile PGConf.dev 2025

最后修改时间:2025-06-21 11:26:11
文章转载自梧桐,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论