在 SaaS 系统中实现多租户(Multi-Tenancy) 是架构设计的核心问题之一,关系到 数据隔离性、安全性、性能可扩展性 以及 开发维护成本。
✅ 一、什么是多租户?
多租户是指:一个应用部署实例服务多个租户(客户),但租户之间的数据相互隔离、互不可见。
✅ 二、实现多租户的三种主流方案
类型 | 说明 | 示例 |
1. 共享数据库、共享表(Shared DB, Shared Schema) | 所有租户共用一套数据库与表,使用 tenant_id 字段区分 | 用户表:user(id, name, tenant_id) |
2. 共享数据库、独立表(Shared DB, Isolated Schema) | 所有租户共用一个数据库,每个租户一套独立表 | 表名:user_1001, user_1002 |
3. 独立数据库(Isolated DB) | 每个租户单独使用一个数据库,表结构一致 | db_tenant_1001.user |
✅ 三、三种方案对比总结
维度 | 共享库共享表 | 共享库独立表 | 独立数据库 |
数据隔离性 | 最弱,需靠逻辑控制 | 中等,物理表隔离 | 最强,物理库隔离 |
扩展性 | 最好,统一管理 | 一般,表数量线性增长 | 较差,数据库连接数受限 |
运维成本 | 最低 | 一般 | 最高 |
安全性 | 最弱 | 中等 | 最强 |
开发复杂度 | 最低 | 中等(需动态表名) | 高(需动态数据源) |
适用场景 | 小型系统,租户轻量 | 中型SaaS,几千租户 | 大客户、高隔离性业务 |
✅ 四、各方案应用示意图
🟩 1. 共享库共享表
SELECT * FROM user WHERE tenant_id = 1001 AND name = 'Tom';
优点:开发简单,运维方便,资源复用率高。
缺点:需严控 SQL 的租户条件,防止越权。
🟦 2. 共享库独立表
表名如:user_1001、order_1001
SELECT * FROM user_1001 WHERE name = 'Tom';
优点:逻辑隔离性强,查询性能好(小表)。
缺点:表数量多,维护复杂,索引难统一。
🟥 3. 独立数据库
数据库如:tenant_1001, tenant_1002
DataSourceRouter.set("tenant_1001");
userDao.selectById(1);
优点:极高隔离性,支持定制化部署。
缺点:资源浪费,跨库事务难实现。
✅ 五、实现技术细节
关键点 | 技术手段 |
租户识别 | 请求中携带 tenantId,如 token、header、subdomain |
数据隔离 | SQL中强制加租户条件 / 动态表名 / 动态数据源 |
访问控制 | 租户上下文管理(如使用 ThreadLocal + AOP) |
ORM支持 | MyBatis、Hibernate 支持拦截 SQL / 动态注入租户字段 |
分库分表中间件 | ShardingSphere、MyCat 实现自动路由 |
✅ 六、细节
问题 | 背后意图 |
多租户有哪些实现方式? | 了解是否具备 SaaS 系统架构经验 |
如何保证数据隔离? | 是否考虑到安全性 + 查询性能控制 |
租户多了如何扩展? | 是否具备高可用、高并发系统的思维 |
如何解决跨租户报表? | 对多租户全局分析的处理方式 |
表结构更新怎么做? | 是否能实现统一维护,防止结构不一致 |
✅ 七、推荐组合
场景 | 推荐方案 |
B端小微商户 | 共享库共享表(开发快) |
多租户企业SaaS平台 | 共享库独立表(性能好) |
政企定制部署、大客户 | 独立库(高隔离) |
评论区