场景特点
SaaS 产品的数据架构有一个绕不开的决策:多个租户的数据如何在存储层组织。这个决策会长期影响成本、隔离性、运维复杂度和产品能力边界,一旦选定再改造成本很高。
核心矛盾在于:租户既希望自己的数据与别人完全隔离,也希望能共享资源以降低单价;而服务方则希望运维尽可能简单、资源利用率尽可能高。三个目标无法同时最大化。
三种常见隔离模式
模式一:独立库
每个租户拥有独立的数据库实例或独立的库。这是隔离强度最高的模式:
- 优势:数据物理隔离,安全性与合规性最好;单个租户的异常(如慢查询、数据膨胀)不会影响其他租户;可按租户单独备份与恢复;
- 劣势:资源利用率低,每个实例都需要预留基础资源;实例数量随租户数线性增长,运维与升级成本高;
- 适用:客户数量有限、单客户价值高、合规要求严格的大型企业客户场景。
模式二:共享库、独立表
所有租户共用一个库,但每个租户有自己的一套表。隔离强度居中:
- 优势:资源利用率优于独立库;数据仍按表分离,单表故障影响范围可控;
- 劣势:表数量随租户数增长,元数据管理压力大;变更表结构时需要遍历所有租户的表,DDL 成本高;
- 适用:租户数量中等、需要一定隔离但希望控制成本的场景。
模式三:共享表加租户字段
所有租户的数据放在同一套表里,通过租户标识字段区分。资源利用率最高:
- 优势:资源利用率最高,运维最简单,表结构变更有一次生效;扩容对所有租户统一生效;
- 劣势:隔离最弱,必须靠应用层与查询条件保证不串数据;单个大租户的查询可能影响其他租户;
- 适用:租户数量多、单租户数据量小、以中小客户为主的标准化 SaaS 产品。
对比与权衡
- 隔离强度:独立库 > 独立表 > 共享表;
- 资源利用率:共享表 > 独立表 > 独立库;
- 运维复杂度:共享表 < 独立表 < 独立库;
- DDL 变更成本:共享表最低,独立表随租户数线性上升;
- 单租户故障影响:独立库最小,共享表最大;
- 单租户恢复能力:独立库可单独恢复,共享表难以做到。
没有最优模式,只有与产品定位匹配的模式。面向中小客户的标准化产品与面向大客户的定制化产品,正确答案通常不同。
共享表模式下的必备防线
如果选择共享表加租户字段(这是多数 SaaS 产品的实际选择),必须建立几道防线来弥补隔离性的不足:
- 强制租户过滤:通过统一的数据访问层或拦截机制,确保所有查询都自动带上租户条件,禁止业务代码手写;
- 索引以租户标识为前缀:让查询天然能利用索引定位到本租户数据,避免全表扫描;
- 越权测试:把「A 租户能否读到 B 租户数据」作为常规测试用例,覆盖所有接口;
- 资源隔离:为大租户设置独立的资源组或查询上限,防止其影响到其他租户;
- 审计与监控:记录跨租户访问行为,异常访问及时告警。
混合模式的实践
现实中很少有产品严格使用单一模式,更常见的是混合方案:
- 按客户分层:中小客户走共享表,大客户单独部署,兼顾成本与满意度;
- 按数据敏感度分层:核心业务数据隔离,日志与统计数据共享;
- 支持迁移通道:设计从共享表迁移到独立实例的工具链,让客户规模增长后可以平滑升级;
- 预留扩展维度:在键设计阶段就考虑未来可能的分库拆分,避免后期大改。
经验小结
多租户隔离方案的选型,本质是在隔离强度、资源成本与运维复杂度之间找平衡点。建议的做法是:先用共享表模式快速起步并验证产品,同时把租户标识贯穿到键设计与访问层;当出现大客户或合规要求时,再通过预留的迁移通道升级为独立部署。这样既避免了一开始的过度设计,也为后续演进留足了空间。
| 核心矛盾 | 租户要求隔离与共享资源,服务方要求运维简单与高利用率 |
|---|---|
| 独立库模式 | 隔离最强、可单独恢复,但资源利用率低、运维成本随租户数线性上升 |
| 独立表模式 | 隔离与成本居中,但表数量膨胀导致元数据压力与 DDL 成本高 |
| 共享表模式 | 资源利用率与运维效率最高,隔离最弱,依赖应用层保证不串数据 |
| 共享表防线 | 强制租户过滤、索引以租户标识为前缀、越权测试、大租户资源隔离与访问审计 |