聊聊多租户是什么
# 聊聊多租户是什么
# 什么是多租户(Multi-Tenancy)?
多租户,简单来说就是:
一个系统、一个数据库、一个部署实例,服务多个“客户”——每个客户就是一个“租户”。
举个例子:
- 你开发了一个在线 CRM 系统,A 公司、B 公司都使用你这套系统,但你并不是为每个公司单独部署一套系统,而是通过一个共享的系统服务他们,这就叫多租户架构。
# 多租户 vs 单租户(区别)
比较项 | 多租户(Multi-Tenant) | 单租户(Single-Tenant) |
---|---|---|
系统部署 | 一个系统服务多个客户 | 每个客户单独部署一套系统 |
数据库 | 共享(带租户隔离)或分库 | 每个客户独立数据库 |
成本 | 成本低、运维集中 | 成本高、灵活性强 |
隔离性 | 数据隔离,资源共享(风险需控制) | 完全隔离,安全性好 |
应用场景 | 典型的 SaaS 系统,如企业协作平台、CRM 等 | 银行、政府等对数据独立性要求高的机构 |
# 多租户架构的实现方式
多租户系统的核心问题是:“如何隔离不同租户的数据和权限?”
根据数据库隔离粒度,多租户有以下 3 种典型实现:
# 1. 共享数据库,共享表(最常见)
- 所有租户共用一套数据库、一张表
- 用一个字段(如
tenant_id
)区分数据归属
SELECT * FROM user WHERE tenant_id = 'A公司'
1
✅ 优点:简单、高性能、节省资源 ⚠️ 缺点:隔离性依赖代码控制,一旦出错可能数据泄露
Java 实现方式:MyBatis + 插件自动加租户过滤条件、ThreadLocal 存当前租户上下文
# 2. 共享数据库,独立 Schema(中等方案)
- 每个租户一个数据库 Schema(逻辑隔离)
- 数据结构一致,表前缀或命名空间不同
SELECT * FROM tenant_a.user
SELECT * FROM tenant_b.user
1
2
2
✅ 优点:隔离性增强,性能仍可控 ⚠️ 缺点:维护成本变高,迁移麻烦
# 3. 独立数据库(最高隔离)
- 每个租户一个独立数据库实例
✅ 优点:隔离性最好,适合重要客户 ⚠️ 缺点:成本高、复杂度高,不利于扩展
# 多租户系统中核心设计点
- 租户识别(Tenant Identification)
- 每个请求中要知道是哪一个租户来的(通常 JWT Token 中携带
tenant_id
) - 登录时就关联租户上下文
- 每个请求中要知道是哪一个租户来的(通常 JWT Token 中携带
- 数据隔离(Data Isolation)
- 查询、更新、删除必须带上租户条件
- 通常在 ORM 层加拦截器(MyBatis Interceptor 或 JPA Filter)自动加条件,防止忘记写
- 权限隔离(RBAC with Tenant)
- 每个租户有自己的角色、权限体系
- “租户 A 的管理员”不能操作“租户 B 的用户”
- 租户配置个性化(Customizable Settings)
- 每个租户可能想配置自己专属的菜单、Logo、权限、字段等
- 系统需要支持动态配置(表驱动 + 多租户字段控制)
- 平台管理员(超级租户)
- SaaS 服务商自己需要有超级管理员,可查看所有租户信息、开通停用租户、监控系统运行等
# 后端开发中如何支持多租户?
以 Java + Spring Boot + MyBatis 为例:
# 1. 租户上下文
通过 ThreadLocal
保存当前请求上下文中的租户 ID:
TenantContext.setTenantId("tenantA");
1
# 2. MyBatis 拦截器添加租户条件
实现 MyBatis 的 Interceptor
,在所有 SELECT
、UPDATE
、DELETE
中自动追加 tenant_id
条件。
SELECT * FROM user WHERE tenant_id = ?
1
# 3. Token 携带租户信息
登录成功后,JWT Token 中包含 tenant_id
,每次请求时从 Header 中解析并设置到上下文。
# 4. 表设计规范
- 每张租户相关的业务表都要加
tenant_id
字段 - 添加复合索引:
tenant_id + 主键
,提升查询性能 - 公共表(如系统字典)可以不加租户字段
# 多租户架构图
+--------------------------+
| 用户浏览器/APP |
+--------------------------+
|
v
+--------------------------+
| API 网关(Gateway) |
| - JWT 鉴权 |
| - 租户识别 |
+--------------------------+
|
v
+--------------------------+
| 应用服务层(Spring Boot)|
| |
| +--------------------+ |
| | 租户上下文管理器 |<--------- 从 JWT 中获取 tenantId
| +--------------------+ |
| |
| +--------------------+ |
| | 权限认证(RBAC/ABAC)|<--------- 基于角色+租户权限控制
| +--------------------+ |
| |
| +--------------------+ |
| | 业务服务(Controller)|
| +--------------------+ |
+--------------------------+
|
v
+--------------------------+
| ORM 层(MyBatis / JPA) |
| - SQL 自动加租户条件 |
| - 拦截器添加 tenant_id |
+--------------------------+
|
v
+--------------------------+
| 数据库(共享数据库) |
| user, order, ... 表 |
| 每张表都带 tenant_id |
+--------------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 总结:什么是多租户?
多租户是让 “一套系统服务多个客户” 的核心能力。
开发时,你要掌握:
知识点 | 技术设计思路 |
---|---|
租户识别 | JWT + Header + ThreadLocal |
数据隔离 | 数据库设计 + ORM 拦截器 |
权限隔离 | 每租户独立 RBAC 模型 |
配置隔离 | 每租户动态参数配置表 |
跨租户管理 | 超级租户账号或平台管理后台 |
上次更新: 2025/6/18 17:55:36