当SaaS的规模经济遇上大客户的定制执念,混合多租户成了唯一的解。
一、从一场事故说起
凌晨两点,我被一条P0级告警震醒:“某头部客户订单接口超时,月GMV千万级业务中断”。
查了半天,问题出在共享服务上——隔壁租户的一次全表扫描,把数据库连接池打满了。我的客户虽然是大户,但因为SaaS架构,被小租户拖了后腿。
那晚过后,我决定:把核心大客户“请”出共享集群。
但这就带来了一个麻烦——APP只有一个,不能给客户强制升级。于是,混合多租户架构应运而生。
二、程序员真懂“多租户”吗?
先别急着撸代码,我们重新理解一下这个概念。
多租户 ≠ 多客户。
多租户的核心是:一套代码实例,服务多个租户,租户之间“看不见对方”。
而根据“共享与隔离”的程度,主流分为三类:
1. 全共享(纯SaaS)
接口:固定不变 服务:同一套后端集群 数据库:同一张表(tenant_id 隔离)或同一个库(schema 隔离) 特点:成本最低,但“吵邻”问题严重 典型:中小型CRM、轻量办公软件
2. 全隔离(独立部署)
接口:每个租户独立域名/IP 服务:独立后端容器 数据库:独立实例 特点:彻底隔离,但成本线性增长 典型:银行、政务、超大型企业
3. 混合多租户(本文主角)
接口:动态切换 服务:中小租户共享 + 大客户独立 数据库:共享库 / 独立库 混合 特点:兼顾成本与性能,但架构复杂度陡增
你现在遇到的情况,99%属于第三类。
三、混合多租户的核心特征(逐条拆解)
1. 一套APP前端,统一商店分发
不是壳包换代码,而是同一个安装包 通过租户标识(登录账号 / 二维码 / 域名参数)动态决定后端地址
2. 部分租户共用服务(中小客户)
共享集群:K8s + 共享数据库 + 连接池 适合流量小、数据敏感度低、预算有限的中长尾租户
3. 大客户独立部署后端(独立接口/服务器)
专属服务集群(可能独立VPC) 独立数据库实例(甚至独立云账号) 独立域名或API网关路径: https://customer-x-api.yourdomain.com
4. 动态端点发现(Endpoint Discovery)
APP启动或登录时,通过“租户路由服务”获取当前租户对应的后端BaseURL 后续所有业务请求直接打到该地址

四、最棘手的挑战:统一APP如何适配多套接口?
这是所有混合多租户架构里,最容易翻车的环节。
错误做法 ❌
在APP里写死 if(tenantId == 'bigCustomer')的硬编码靠发版更换配置(iOS审核一周,客户早就炸了)
正确做法 ✅
方案A:启动时发现(推荐)
用户输入租户标识(如企业码)
→ 调用公共路由服务 `https://router.yourdomain.com/resolve?code=xxx`
→ 返回 { apiBaseUrl: "https://tenant5-api.yourdomain.com", version: "v2" }
→ APP 动态替换所有后续请求的BaseURL
优点:灵活、无需发版
风险:路由服务挂了,所有租户全挂(必须高可用+多级缓存)
方案B:登录时下发
用户输入账号 → 登录接口(统一入口) 登录成功后,在Token Payload中携带 api_gateway字段后续请求自动拼接到该网关地址
优点:减少一次RTT(往返时间)
缺点:退出重登才能切换环境
方案C:基于域名的自动识别(Web + App混合)
给不同租户分配不同子域名: customer-a.app.com、customer-b.app.comAPP通过 window.location.host或深度链接解析租户ID适合从企业微信、钉钉跳转的场景

五、后端架构怎么做?一张图讲清楚
共享区(中小租户)
统一API网关(*.shared.yourdomain.com)
├─ 租户A(tenant_id=1001)
├─ 租户B(tenant_id=1002)
└─ 租户C(tenant_id=1003)
↓
共享数据库(tenant_id分表/分库)
独立区(大客户)
独立网关(customerX.yourdomain.com)
↓
独立服务实例(4核8G起步)
↓
独立数据库(MySQL / RDS)
统一控制面
租户路由注册中心(etcd + Redis) 租户生命周期管理(创建、升级、迁移)
核心操作:当客户从“共享”升级为“独立部署”时,做一次数据迁移 + 路由切换,APP无感知。
六、避坑指南(每一个都是血泪教训)
坑1:Token跨租户混用
现象:独立租户的用户Token能调通共享租户接口 原因:JWT签名密钥统一 解:不同租户集群使用不同签名密钥,或在Token中强制校验 tenant_id与请求Host是否匹配
坑2:共享租户的“吵闹邻居”影响路由服务
共享集群内某个租户故障导致整个网关CPU飙高 → 路由服务响应超时 → 所有租户无法发现端点 解:路由服务必须独立部署(甚至独立云账号),与业务网关彻底隔离
坑3:独立部署租户的回调与Webhook无法到达
客户独立部署后,回调地址还是指向共享集群的 webhook.shared.com解:每个租户独立维护配置中心,支持动态回调域名
坑4:监控与告警分裂
共享集群一套Prometheus,独立集群各搞各的 → 故障定位难 解:统一可观测平台(Thanos + Jaeger),按 cluster_id区分租户

七、什么时候该上混合多租户?
不是所有场景都需要。满足以下3条以上,可以动手:
存在月活超10万的大租户,且与中小租户混用导致性能投诉 有合规要求(数据本地化、等保三级),但又不愿完全独立开发 共享集群P99延迟因某一租户波动超过3倍 你的SaaS客单价出现两极分化(小客户5000/月) 客户明确要求“可一键从共享迁移到独立”

八、总结:混合多租户的本质
它不是纯粹的技术架构,而是商业策略在工程上的投影。
对中小租户:卖标准化SaaS,赚规模效益 对大租户:卖专属部署,赚溢价和服务费 对技术团队:维护两套运行模式,但共享同一套代码资产
如果你能把混合多租户玩明白,你就同时懂了:
如何做SaaS(降本) 如何做私有化(交付) 如何做渐进式架构演进(平衡)
最后送大家一句话:
没有最好的架构,只有最匹配商业模型的架构。混合多租户,就是SaaS企业长大后的必然妥协与智慧。
评论区聊聊:你现在用的是哪种多租户模式?踩过哪些“吵邻居”的坑?
IT技术交流群:
软件接单交流群:

夜雨聆风