多租户缓存隔离需强制将租户ID嵌入缓存键,结合网关校验、分级策略、no-cache拦截与可观测性验证。例如键模板为"{{ .TenantID }}/{{ .ModelName }}/v{{ .Version }}",并按租户等级设置TTL、降级与穿透控制。

核心在于让缓存键天然携带租户身份,避免不同租户共用同一缓存条目。单纯靠路径或模型名做缓存,必然在多租户场景下引发碰撞和数据错乱。
强制缓存键注入租户上下文
不能只依赖请求路径或模型名称生成缓存 key,必须把租户标识作为缓存 key 的刚性组成部分。
- 在网关路由规则中显式声明 mandatory_fields: [TenantID, ModelName],缺失任一字段直接拦截(403)
- 使用带命名空间的 key 模板,例如:"{{ .TenantID }}/{{ .ModelName }}/v{{ .Version }}",确保 tenant_a 和 tenant_b 即使调用同名模型 finance-llm,缓存 key 也完全隔离
- 对租户 ID 做格式校验(如正则匹配 ^[a-z0-9]{6,16}$),防恶意构造或空值绕过
按租户等级动态分层缓存
不同租户对一致性、延迟、容错的要求不同,缓存策略不能“一刀切”,需分级响应。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 白金级租户:TTL 60s + 本地内存缓存,Redis 延迟超 100ms 自动降级为本地缓存并延长 TTL 50%
- 普通级租户:TTL 30s,统一走集群 Redis,命中失败时返回陈旧数据(stale-while-revalidate)
- 试用级租户:TTL 仅 5s,且不启用自动降级,直接穿透至后端,避免低价值请求污染高价值缓存空间
拦截冷启动雪崩与 no-cache 标签滥用
当某租户主动设置 Cache-Control: no-cache 时,若未加约束,会瞬间击穿所有缓存层,冲击下游模型服务。
- 网关层拦截并重写该头:将 no-cache 转为 max-age=0 + private,并附加 X-Portkey-Tenant-Class 头供后续策略识别
- 对高优租户的 no-cache 请求,强制启用“影子缓存”——异步预热下一组可能命中的 key,维持底层服务水位平稳
- 配置熔断阈值:单租户 5 分钟内缓存穿透率 > 80%,自动触发限流并告警,防止低优先级租户抢占资源
监控与验证双闭环
缓存是否真隔离,不能只靠配置,得靠可观测性验证。
- 日志中强制打标 tenant_id 和 cache_key_hash,排查时可快速定位跨租户 key 冲突
- 构建缓存探针接口:输入 tenant_id + model_name,返回当前缓存命中率、key 命中分布、TTL 剩余时间,用于巡检
- 每日自动化比对:扫描 Redis 中所有 cache:* key,检查是否存在无 tenant_id 前缀或前缀重复的异常 key










