多租户基础
说实话,多租户这个概念我十年前刚入行时也迷糊过。当时在一家创业公司做SaaS,老板说“一个系统给一百个客户用,数据不能串”。我第一反应是——那不就每个客户装一套数据库?后来被运维大哥骂了一顿,才知道那叫“单租户部署”,跟多租户完全是两回事。
什么是多租户
多租户(Multi-Tenancy)是一种软件架构。它让同一套应用实例同时服务于多个客户(租户),而且每个租户感觉自己在独占系统。
举个例子。你打开钉钉或飞书,看到的组织、聊天记录、审批流,跟隔壁公司完全不一样。但底层跑的是同一个服务。我习惯这么理解:多租户就像一栋写字楼,不同公司在不同楼层办公。共享大厅、电梯、水电,但门禁和房间钥匙是独立的。
核心特征:共享资源 + 逻辑隔离。两者缺一不可。
我遇到过最经典的误解——“把每个客户的数据放在不同数据库就算多租户”。不对。那叫多实例,不是多租户。多租户的关键是共享计算资源(CPU、内存、连接池),同时通过租户标识来路由和隔离数据。
租户隔离的核心挑战
隔离怎么做?做不好就是事故。我整理了几条硬骨头:
| 挑战维度 | 通俗解释 | 我踩过的坑 |
|---|---|---|
| 数据隔离 | A租户不能看到B租户的任何记录 | 曾经有个SQL漏了WHERE tenant_id = ?,结果报表数据混了,被客户投诉到CEO |
| 性能隔离 | 一个租户搞大查询,不能拖垮其他人 | 我们遇到过某个租户定时跑全量统计,把数据库连接池占满,所有租户一起卡顿 |
| 安全隔离 | 不能越权操作,密钥防泄露 | 嗯,这就是咱们这门课要重点讲的——密钥权限怎么做到租户级 |
| 配置隔离 | 租户自定义字段、工作流、UI主题不能干扰全局 | 早期我们直接把配置放内存Map,租户一多就OOM |
避坑提示:我曾经在一个项目里只做了数据隔离,没做连接池隔离。结果一个租户的慢查询把整个Tomcat的数据库连接耗尽,其他租户全部超时。后来我给每个租户分配了独立的连接池阀值,才算稳住。
常见隔离模型:SaaS / PaaS / IaaS
这三个词大家天天听,但在多租户语境下,它们代表不同的隔离层次。简单说:
- SaaS(软件即服务):应用层隔离。租户共享应用进程,通过租户ID在代码层做隔离。比如Salesforce、钉钉。
- PaaS(平台即服务):运行时/中间件层隔离。平台提供公共组件(数据库、消息队列),每个租户可创建独立的“沙箱”或“环境”。比如Heroku、Kubernetes Namespace。
- IaaS(基础设施即服务):硬件/虚拟化层隔离。每个租户有独立的虚拟机、容器或物理服务器。比如AWS EC2、OpenStack。
我自己的经验是:SaaS的隔离最难做,因为共享最多,出问题的面也最广。PaaS和IaaS的租户边界更清晰,但资源浪费也更大。你想想看,给每个租户一台虚拟机,成本谁扛得住?
上图其实能看出一个趋势:越往左,共享越多,隔离成本越低,但实现难度越大。我们这门课的核心就是教你怎么在SaaS这种最“挤”的模式下,把密钥和权限隔离做到位。
那密钥隔离为什么要单独拿出来讲?
你想想看,普通数据隔离用tenant_id筛选就行。但密钥不一样——它是用来加解密、签名、认证的。如果A租户的密钥被B租户拿到,等于银行保险柜的钥匙落到外人手里。而且密钥还牵扯到HSM(硬件安全模块)、KMS(密钥管理服务)、权限策略……隔离的层级要比普通数据深得多。
我个人习惯把密钥隔离分成三块:存储隔离(不同租户的密钥不能放同一个数据库表?还是加前缀?)、访问隔离(谁有权限调用哪些密钥)、审计隔离(密钥操作日志能精确追溯到租户)。后面几章咱们会挨个拆解。
记住一个原则:不要在代码里写死任何租户的密钥。哪怕开发环境也不行。我犯过这个错——测试库忘了清理,结果生产环境代码里还残留着某客户的生产密钥,差点出合规事故。
好了,多租户基础就聊到这儿。你脑子里的那个“共享但不串”的模型,应该已经清楚了。下一块内容咱们会动手搭建一个最简单的多租户Spring Boot项目,把租户上下文传递机制跑通。嗯,到时候你会看到代码里是怎么加threadLocal和过滤器做隔离的。