租户隔离与数据生命周期:API 授权正确也可能跨租户泄漏
API 入口校验了租户身份,后台批任务却漏了 tenant_id 过滤——授权正确的入口保护不了缓存键、搜索过滤、导出和运维脚本。本页定义隔离层级、贯穿所有副本的租户边界、删除与保留协议。公平配额与容量分摊的算例见容量推导与故障余量。
隔离贯穿所有副本
同库tenant_id过滤、独立schema、独立库和独立集群提供不同的成本、性能与故障隔离。共享库中漏一个后台查询条件可能跨租户泄漏,API入口授权正确也不能保护缓存键、搜索过滤、导出和运维脚本。标识租户从可信上下文获得,不接受调用方任意传入即授权。
缓存键、幂等键与唯一键应包含真实身份域;否则租户A业务单123可能与B冲突或读到B缓存。数据库连接池的会话变量复用也需finally恢复,不能把某次setTenant当成永久安全隔离。数据正确性的观察信号(复制延迟、CDC lag、投影版本差、回填进度、隔离冲突、保留执行、对账差异)应成为可观测状态,仅有 CPU 与请求错误率无法显示业务数据是否落后;数据校验应比较稳定的键空间、版本区间和业务聚合,避免将正在迁移的临时差异误判为错误,发现差异后修复操作要记入审计。
容量与成本的公平分摊
总峰值1万请求/秒,最大租户占60%。共享池即使总体CPU70%,单租户也可能耗尽连接与队列。配额需同时覆盖并发、速率、排队、存储与昂贵查询,给关键租户保底与突发上限。独立池隔离更强,但空闲浪费、升级和运维成本增加。
比较A共享基础资源加有限租户类别与B大租户独立部署时,用每租户成功请求成本、期限违约、故障影响范围和操作人力同口径计算。不能把所有用户ID做指标标签来证明公平,应以受控账单/追踪查个体,有限维度做在线聚合。
删除与保留协议
数据生命周期包括主库、缓存、搜索、对象、日志、备份与第三方导出。业务软删先限制访问,物理清除和备份到期分别有期限;不可变备份通常不能即时逐条删除,应通过隔离访问、到期销毁与恢复后重施删除记录满足既定策略。这里是技术设计,不代替具体法域要求。
删除也需有稳定事件与墓碑,防旧重放复活。离职/租户迁移时轮换凭据、停止后台任务与导出权限,不能只删一张租户表。租户迁移和删除应具备可审计的状态机,覆盖主库、缓存、搜索索引、消息、对象存储、日志和备份;删除证明要声明哪些副本仍在保留期内。分区归档、冷热分层与备份保留要区分在线查询、合规保存、事故恢复和长期分析用途;保留规则改变后,还需验证下游副本和分析仓库的删除传播。
验证方法
创建A/B同名对象与同业务单号,覆盖API、缓存、搜索、批处理、导出和恢复。A删除后重放旧事件,必须仍不可访问;恢复备份后先应用删除/权限账本再开放流量。注入连接上下文未清理得到反例,修复后验证后继无租户任务不继承A。这些验证可在隔离环境执行,本轮未运行,步骤与预期按上文保留。
限界上下文与租户身份传递
本页前面讲"隔离贯穿所有副本",但租户身份不是一个字段,而是上下文之间必须传递的可信事实。DDD 的限界上下文给了判断标准:每个上下文有自己的统一语言,租户在这个语言里的含义必须一致——是"数据归属",还是"计费主体",还是"访问控制域"?三者混淆,隔离就在某个上下文里失效。
传递规则:租户身份由可信来源(认证令牌的 claim 或网关签名头)产生,在上下文边界转换成该上下文自己的语言,随聚合、领域事件、集成事件、投影键与查询条件一路传递。不允许下游从业务字段(如订单号前缀)反推租户,也不允许某个上下文"默认单租户"。
执行 python3 labs/context_model.py tenant_propagation:模型检查四个检查点——聚合键、事件负载、投影键、查询过滤;预期全部存在,故意丢掉事件负载一处时输出 missing_when_dropped=["event_payload"]。这说明只要一个上下文不传租户,下游投影就会把不同租户的数据混在一起,而 API 层的授权检查完全看不出问题——这正是本页开头"API 授权正确也可能跨租户泄漏"的 DDD 版本。
模型之外还要检查语义一致性:同一个租户 ID 在结算上下文表示计费主体、在内容上下文表示数据归属,如果两个上下文合并成一个报表,报表口径就会错。上下文映射表里要写明每个上下文中"租户"的确切含义与来源。
两个合理选择:A 全局租户 ID,所有上下文直接使用,简单但把计费与数据归属绑死,未来拆分计费主体时全线改动;B 各上下文用自己的租户语言,边界处做显式转换并记录映射。本例选 B,代价是每个边界要维护转换与审计;收益是上下文可以独立演进,且转换点本身就是隔离审计的天然位置。
架构师变化条件
把最大租户独立部署:配额协议变为"独立池+共享池的跨租户目录",迁移本身是一次零停机搬迁(见零停机 schema 迁移),删除与备份协议按新域重写。合规要求"30 天内彻底删除"时,不可变备份策略与保留期直接冲突,需在备份设计期选择可到期销毁的保留结构,而不是事后补删。每次变化重画"副本×生命周期"矩阵并标注哪一格做不到即时删除。
闭卷验收
本页 8 道闭卷题收进了下方自测面板:先回忆,再展开参考答案与评分点,最后给三档自评。