1. 多租户概述
1.1 SaaS 多租户定义
多租户(Multi-Tenancy) 是 SaaS 架构最核心的隔离模式。它允许一个应用实例同时服务多个租户(Tenant),每个租户在逻辑上拥有独立的数据空间与配置,但共享同一套底层基础设施与代码版本。
与传统的单租户部署不同,多租户架构通过资源复用大幅降低运维成本,同时必须保证租户之间的数据不可见、不可篡改。租户可以是一个企业、一个部门、一个项目组,甚至是一个独立用户——取决于业务模型的粒度。
关键区分: 多租户 ≠ 多用户。多用户指同一租户内的多个账号;多租户指多个完全隔离的组织共享同一系统实例。
1.2 核心挑战:数据隔离、性能、安全
多租户架构在带来成本优势的同时,也引入了三个必须解决的工程挑战。下表总结了每个挑战的核心问题与典型应对策略:
| 挑战维度 | 核心问题 | 典型应对策略 |
|---|---|---|
| 数据隔离 | 租户 A 的数据不能被租户 B 访问或泄露 | 独立数据库、共享数据库独立 Schema、共享表 + Tenant ID 行级过滤 |
| 性能 | 一个租户的突发流量不能影响其他租户的响应时间 | 连接池隔离、租户级限流、缓存分片、资源配额管理 |
| 安全 | 鉴权绕过、跨租户越权、数据注入、身份冒用 | 租户上下文传递、请求拦截链路、参数级权限校验、审计日志 |
常见误区: 很多团队只关注数据库层的 Tenant ID 过滤,却忽略了 API 网关层、服务间 RPC 调用、缓存层和日志输出中的租户上下文传递,导致数据泄露漏洞。
1.3 租户模型:单租户 vs 多租户
选择单租户还是多租户,直接影响系统的隔离粒度、运维成本和扩展方式。下表从多个维度进行对比:
| 对比维度 | 单租户(Single-Tenant) | 多租户(Multi-Tenant) |
|---|---|---|
| 部署方式 | 每个租户独立部署一套应用 + 数据库 | 所有租户共享同一套应用实例 |
| 数据隔离 | 物理隔离,天然安全 | 逻辑隔离,依赖代码与架构保障 |
| 运维成本 | 高(版本升级、补丁、监控需逐租户执行) | 低(一次部署,全局生效) |
| 资源利用率 | 低(每个租户预留峰值资源) | 高(租户间资源复用,弹性伸缩) |
| 定制化能力 | 强(可独立修改代码、配置、数据库结构) | 弱(定制化需通过 Feature Flag 或插件机制) |
| 适用场景 | 大型企业、金融、医疗等强合规行业 | 中小客户、标准化产品、快速扩张的 SaaS |
在实际工程中,还存在混合模型:核心租户使用独立数据库(单租户模式),中小租户共享数据库(多租户模式),通过路由层根据租户等级动态切换数据源。
1.4 多租户数据隔离架构总览
下图展示了多租户系统中从请求入口到数据存储的完整隔离链路,重点标注了鉴权拦截的关键位置:
1.5 租户上下文传递链路
在多租户系统中,租户上下文(Tenant Context) 必须贯穿整个请求生命周期。以下是典型的传递链路步骤:
- 请求入口:客户端携带租户标识(如
X-Tenant-ID请求头或 JWT 中的tenant_id声明)。 - 网关解析:API 网关提取租户标识,校验格式与合法性,注入到请求上下文。
- 鉴权拦截器:验证 Token 有效性,确认当前用户属于该租户,防止跨租户 Token 滥用。
- 服务间传递:通过 RPC 拦截器或消息头将租户上下文透传到下游微服务。
- 数据访问过滤:ORM 拦截器或数据库中间件自动追加
WHERE tenant_id = ?条件。
工程要点: 租户上下文必须使用 ThreadLocal(Java)或 Context(Go/Python)在单请求线程内传递,并在请求结束后清理,防止内存泄漏导致跨租户数据错乱。
1.6 三种数据隔离模式对比
根据隔离强度与资源复用程度,多租户数据隔离通常分为三种模式。下表从多个维度进行对比:
| 隔离模式 | 隔离强度 | 资源复用 | 运维复杂度 | 典型场景 |
|---|---|---|---|---|
| 独立数据库 | 最高(物理隔离) | 最低 | 高(需管理多个 DB) | 金融、医疗、大型企业 |
| 独立 Schema | 中(逻辑隔离) | 中 | 中(Schema 管理) | 中型 SaaS、区域隔离 |
| 共享表 + Tenant ID | 低(行级隔离) | 最高 | 低(单库单表) | 标准化产品、海量小租户 |
在实际架构中,这三种模式可以混合使用:例如,免费版租户使用共享表,付费版租户使用独立 Schema,企业版租户使用独立数据库。路由层根据租户等级动态选择数据源。
安全提醒: 共享表模式中,
tenant_id 过滤条件必须由后端强制注入,不能依赖前端传递。任何 SQL 拼接遗漏都可能导致全量数据泄露。