1. SaaS 多租户基础概念

1.1 什么是 SaaS

SaaS(Software as a Service,软件即服务)是一种通过互联网交付软件应用的模式。用户无需在本地安装、维护或管理软件,而是通过浏览器或 API 按需访问云端的服务。服务提供商负责底层基础设施、中间件、应用运行时的全生命周期管理。

SaaS 的核心特征包括:

  • 多租户架构:一套应用实例同时服务多个客户(租户),租户之间逻辑隔离。
  • 按需付费:用户按使用量(用户数、存储、API 调用次数)订阅,无需一次性购买许可证。
  • 零运维:升级、补丁、扩缩容由提供商自动完成。
  • 弹性扩展:基于云原生基础设施,支持从单租户到百万级租户的水平扩展。
关键指标:成熟的 SaaS 平台通常要求租户隔离延迟 < 5ms、租户元数据查询 QPS > 10,000、单租户数据恢复 RTO < 15 分钟。

1.2 多租户的定义

多租户(Multi-Tenancy)是指同一套软件实例能够同时服务多个相互隔离的租户。每个租户拥有独立的逻辑视图,包括用户身份、权限、配置、业务数据,但共享底层计算、存储和网络资源。

多租户与单租户的核心区别:

维度 单租户 多租户
实例数量 每个客户独立部署一套实例 所有客户共享一套实例
资源利用率 低(存在资源碎片) 高(通过池化提升利用率)
运维成本 线性增长(N 个客户 = N 倍运维) 亚线性增长(新增租户几乎零成本)
隔离强度 物理/虚拟化隔离 逻辑隔离为主,可叠加物理隔离
升级影响面 逐个升级,影响单个客户 一次升级影响所有租户(需灰度)

1.3 租户隔离模型

租户隔离模型决定了数据如何在存储层进行分离。主流模型有三种:Database-per-Tenant、Schema-per-Tenant、Shared Table。选择哪种模型直接影响鉴权拦截链路的实现复杂度、数据恢复策略和自动化部署流水线。

1.3.1 Database-per-Tenant(独立数据库)

每个租户拥有独立的物理数据库实例或逻辑数据库。隔离级别最高,数据完全独立,备份恢复互不影响。适用于金融、医疗等强合规场景。

  • 优点:最强数据隔离;支持按租户独立扩缩容;故障域最小。
  • 缺点:资源开销大;连接池管理复杂;跨租户查询困难。
  • 鉴权拦截特点:在连接层通过租户 ID 路由到对应数据库,鉴权拦截主要在网关层完成。

1.3.2 Schema-per-Tenant(独立 Schema)

所有租户共享同一个数据库实例,但每个租户拥有独立的 Schema(命名空间)。表结构相同,数据按 Schema 隔离。适用于中等规模 SaaS(几百到几千租户)。

  • 优点:资源利用率高于独立数据库;支持 Schema 级备份;迁移成本较低。
  • 缺点:共享数据库实例,存在资源争抢;跨 Schema 查询仍需应用层聚合。
  • 鉴权拦截特点:在 ORM 层或数据访问层动态切换 Schema,鉴权拦截需同时验证租户身份和 Schema 映射。

1.3.3 Shared Table(共享表)

所有租户的数据存储在相同的表中,通过 tenant_id 列进行逻辑区分。隔离级别最低,但资源利用率最高。适用于超大规模、低合规要求的场景(如内部工具、日志分析)。

  • 优点:存储成本最低;查询性能最优(单表扫描);运维最简单。
  • 缺点:数据隔离完全依赖应用层;误操作可能导致租户数据泄露;备份恢复必须全量处理。
  • 鉴权拦截特点:所有 SQL 查询必须强制附加 WHERE tenant_id = ? 条件,鉴权拦截需在 SQL 解析层或 ORM 拦截器注入租户过滤。
常见陷阱:选择 Shared Table 模型时,如果鉴权拦截链路未在 SQL 层面强制注入 tenant_id 过滤,极易出现跨租户数据泄露。建议在自动化部署流水线中加入 SQL 静态扫描规则,检测是否存在缺失 tenant_id 的查询。

1.4 三种隔离模型对比

对比维度 Database-per-Tenant Schema-per-Tenant Shared Table
隔离强度 最高 中 低
资源开销 高(每个租户独立实例) 中(共享实例,独立 Schema) 低(共享实例和表)
租户上限 几百 几千 百万级
备份恢复粒度 按租户独立备份 按 Schema 备份 全量备份
鉴权拦截复杂度 低(路由到独立 DB) 中(动态 Schema 切换) 高(SQL 级过滤注入)
适用场景 金融、医疗、合规敏感 中型企业 SaaS 超大规模、低成本场景

1.5 隔离模型选择对鉴权拦截链路的影响

鉴权拦截链路的核心职责是:在请求到达业务逻辑之前,完成租户身份识别、权限校验、数据路由规则注入。不同隔离模型决定了拦截链路的实现位置和复杂度:

  • Database-per-Tenant:拦截链路主要在 API 网关层完成租户识别,然后路由到对应数据库连接池。数据层无需额外过滤。
  • Schema-per-Tenant:拦截链路需要在网关层识别租户,并在 ORM 上下文(如 ThreadLocal)中设置当前 Schema。数据访问层自动切换。
  • Shared Table:拦截链路必须在 SQL 执行前注入 tenant_id 过滤条件。通常通过 MyBatis 拦截器、Hibernate 过滤器或数据库代理(如 ProxySQL)实现。
自动化部署建议:在 CI/CD 流水线中,建议为每种隔离模型配置独立的鉴权拦截测试套件。例如:Shared Table 模型必须包含 SQL 注入测试用例,验证所有 SELECT/UPDATE/DELETE 语句是否自动追加 tenant_id 条件。

1.6 隔离模型架构图

下图展示了三种隔离模型在 SaaS 多租户架构中的部署形态,以及鉴权拦截链路在每一层的作用位置:

SaaS 多租户隔离模型架构图 SaaS 多租户隔离模型架构 API 网关 / 鉴权拦截层 租户身份识别 → Token 校验 → 权限判定 → 路由规则注入 应用服务层 业务逻辑处理 · 租户上下文管理 · ORM 拦截器 Database-per-Tenant 租户 A → DB_A 租户 B → DB_B 租户 C → DB_C 隔离强度:最高 Schema-per-Tenant 共享实例 DB 租户 A → Schema_A 租户 B → Schema_B 隔离强度:中 Shared Table 单表 + tenant_id 所有租户共享 SQL 级过滤 隔离强度:低 鉴权拦截链路关键点: ① Database-per-Tenant:网关层路由到独立连接池 ② Schema-per-Tenant:ORM 层动态切换 Schema ③ Shared Table:SQL 拦截器强制注入 tenant_id 过滤

1.7 隔离模型选择决策流程

在实际 SaaS 架构设计中,隔离模型的选择通常遵循以下决策树:

  1. 合规要求:如果租户数据必须物理隔离(如 GDPR、HIPAA),优先选择 Database-per-Tenant。
  2. 租户规模:预期租户数 < 500 且预算充足,选 Database-per-Tenant;500~5000 选 Schema-per-Tenant;> 5000 考虑 Shared Table 或混合模型。
  3. 运维能力:团队是否有能力管理大量数据库连接池和备份策略?如果否,优先 Schema-per-Tenant 或 Shared Table。
  4. 鉴权拦截复杂度:如果团队对 SQL 层拦截器不熟悉,避免选择 Shared Table,防止数据泄露。
  5. 混合模型:大型 SaaS 平台通常采用混合策略——高合规租户使用独立数据库,普通租户使用共享表,通过统一的鉴权拦截链路进行路由分发。
最佳实践:在自动化部署流水线中,建议将隔离模型作为部署配置参数(如 --isolation-model=shared-table),CI/CD 根据参数自动选择对应的鉴权拦截插件、数据库初始化脚本和测试套件。这样一套流水线即可支持所有隔离模型。