3、隔离原理:多租户隔离、数据隔离、环境隔离
隔离这件事,说白了就是「谁的数据归谁,谁的密钥归谁」。你想想看,一个系统里同时跑着几十家客户,要是A租户能看到B租户的账单,或者测试环境的密钥不小心配到了生产环境……那画面太美我不敢看。
我个人习惯把隔离拆成三个维度来设计:多租户隔离解决「人与人的数据不混」;数据隔离解决「同一个人能看哪些字段」;环境隔离解决「开发测试生产各玩各的」。三条线各守一摊,但又互相咬合。
下面我一个一个说,顺带聊聊我在项目里踩过的坑。
3.1 多租户隔离:你的数据就是你的
多租户隔离的核心问题就一个:怎么让不同租户的数据在同一套系统里和平共处。最常见的做法有三种,我直接拉个表对比:
| 方案 | 隔离粒度 | 运维成本 | 安全等级 | 适用场景 |
|---|---|---|---|---|
| 共享数据库 + 租户ID字段 | 行级 | 低 | ★☆☆ | 中小型SaaS、长尾客户 |
| 独立Schema(同一库) | 表级 | 中 | ★★☆ | 中型客户、需要部分隔离 |
| 独立数据库 | 库级 | 高 | ★★★ | 金融、医疗、高合规场景 |
共享数据库+租户ID 是最省事的。每个表加个 tenant_id,查询时WHERE条件带上就行。但这里有个坑——只要有一条SQL忘记过滤,数据就串了。
独立Schema 是我个人比较推荐的中庸方案。每个租户一个Schema,表结构相同,但数据物理隔离。查询时切换 search_path 就行。我在一个教育SaaS平台上用过这套,几百个租户跑得挺稳。
独立数据库 是终极方案。隔离最彻底,但运维成本也最高——连接池、迁移、备份都得乘以租户数量。我记得在做一个金融系统时,合规要求强制独立数据库,连数据库账号都不能复用。那段时间DBA团队天天加班……
3.2 数据隔离:精细到字段级别
多租户隔离解决的是「租户与租户之间」的问题。但同一个租户内部,不同角色能看到的数据也不一样。这就是数据隔离要干的活。
数据隔离通常分三个层次:
- 行级隔离——同一张表,不同用户只能看到属于自己的行。比如销售只能看自己的客户,经理才能看全团队。
- 字段级隔离——同一行数据,不同用户看到的字段不同。比如HR能看到薪资,部门主管只能看到职级。
- 加密隔离——敏感字段密文存储,即使用户有查询权限,没有密钥也解不开。
我重点说说字段级隔离,因为这是最容易出纰漏的地方。
有次在ERP项目中,财务角色打开员工信息页面时,意外看到了「薪资等级」字段——原本这个字段只对HR开放。排查下来发现,后端接口返回了全部字段,前端只是用v-if控制显示。这种「前端隔离」等于没隔离,懂点网络的人抓个包就破了。
正确的做法是:后端根据角色动态过滤字段,返回的数据里压根就不包含无权限的字段。前端只负责渲染。
行级隔离在SQL层面实现比较成熟。PostgreSQL的 Row-Level Security 可以直接在表上定义策略,不用改业务代码。MySQL 8.0 也有类似能力。我的建议是:能用数据库原生RLS就别自己写WHERE条件,数据库层面的隔离比应用层靠谱得多。
加密隔离一般在两种场景下用:一是身份证号、银行卡号等强敏感字段;二是跨环境传输时的脱敏需求。我个人习惯是在ORM层加一个透明加密注解,读时自动解密,写时自动加密——这样业务代码完全无感。
LIKE 了。折中方案是存一个加密字段用于精确匹配,再加一个脱敏字段用于模糊搜索。比如身份证存「加密密文 + 前6后4明文」。
3.3 环境隔离:密钥和配置别乱串
环境隔离解决的是「开发、测试、生产各玩各的」。听起来简单,但我见过太多把生产密钥配到测试环境,或者测试环境连了生产库的案例。
环境隔离的核心有三条:
- 密钥分离——每个环境独立签发密钥,不能复用。开发环境用自签名证书,生产环境用CA签发的证书。
- 配置隔离——数据库地址、API端点、日志级别等配置与环境绑定。我建议用配置中心(如Nacos、Consul)做环境命名空间,而不是靠配置文件里的profile来区分。
- 网络隔离——生产环境应该在其他环境无法直接访问的网段里。开发环境连不上生产库,这是基本原则。
还有一个容易忽略的点:日志中的密钥泄露。很多开发为了调试方便,会在日志里打印请求参数或数据库连接串。一旦这些日志被传到日志中心,等于把密钥公开了。我建议在日志采集端加一个脱敏过滤器,匹配到 password、secret、 等关键字时自动替换成 ***。
3.4 三种隔离如何协同
三种隔离不是各管各的,而是层层递进、互相补充的关系。多租户隔离划定了大边界,数据隔离在边界内做精细管控,环境隔离则保证这些规则在不同生命周期里一致执行。
下面这张图把整体架构串起来了:
看到这张图的结构了吧?从上到下是「边界 → 精细 → 一致性」的递进关系。没有多租户隔离,数据隔离做得再细也白搭——因为A租户的数据可能直接跑到B租户的视野里。没有数据隔离,多租户隔离只是「能看见」和「看不见」的区别,同一个租户内的敏感字段照样裸奔。而环境隔离是托底的那层——它保证你在测试环境折腾时,不会把生产数据搞崩。
最后放一个三者对比的表格,方便你对照设计自己的隔离方案:
| 隔离维度 | 解决什么问题 | 核心手段 | 最容易踩的坑 |
|---|---|---|---|
| 多租户隔离 | 租户间数据不串 | 独立数据库/Schema/租户ID | SQL漏写租户过滤条件 |
| 数据隔离 | 同一租户内权限分级 | RLS、字段过滤、加密存储 | 前端隔离代替后端隔离 |
| 环境隔离 | 开发测试生产互不影响 | 密钥分离、配置命名空间、网络隔离 | 跨环境复用密钥或配置 |
嗯,三种隔离的原理就这些。说起来不复杂,但每一条我都拿真金白银的故障换过经验。你设计系统时把这三层想清楚,权限隔离这块的基本盘就稳了。