缓存键设计需严格区分静态与动态请求:静态键仅含URL路径、标准化参数及版本标识,忽略客户端差异;动态键必须显式编码用户身份、会话、租户等上下文;混合场景采用分层命名空间结构,并通过元数据驱动和自动化校验保障边界清晰。

缓存键设计的关键,是让“相同语义的请求”命中同一份缓存,而“不同语义的请求”绝不混淆。静态与动态请求的本质区别在于:是否依赖用户身份、会话状态、设备特征、时间上下文等运行时变量。边界划分不清,就会导致缓存污染、数据错乱或隐私泄露。
静态请求的缓存键:只含确定性、不可变因子
这类请求的结果对所有用户都一致,且不随时间频繁变化。缓存键应仅由资源本身的固有属性构成:
- URL路径(如 /api/v1/products),不含查询参数中的随机值或会话ID
- 关键业务参数(如 category=electronics&sort=price_asc),但需标准化顺序、过滤空值和无关参数(如 utm_source)
- 内容版本标识(如 v=2.1 或基于文件哈希的 hash=abc123),用于主动失效
- 忽略客户端差异:不包含 User-Agent、Accept-Language 等头字段,除非业务明确要求多语言独立缓存
动态请求的缓存键:显式纳入可变上下文维度
只要响应内容因用户、设备或场景而异,就必须把相关维度编码进缓存键,否则会跨用户返回错误数据:
- 用户身份:如 user_id=789 或 auth_token_hash=xyz(避免明文 token)
- 会话标识:如 session_id=abc456,适用于未登录但有临时会话的场景
- 租户/店铺上下文:如 tenant_id=shop-a、store_view=en_US
- 设备能力标记:如 device=mobile&dpi=2x,用于响应式资源适配
- 时间敏感标记:如 date=2026-09-16,适用于按日刷新的报表类接口
混合场景的键结构:用命名空间+分层拼接防冲突
很多接口既含公共部分又含个性化部分。推荐采用分段式结构,用冒号或下划线分隔逻辑层级,提升可读性和可维护性:
- static:product:detail:id=123 → 全局商品详情(静态)
- dynamic:user:profile:user_id=789:locale=zh_CN → 用户个人资料(动态)
- hybrid:cart:items:user_id=789:session_id=abc456 → 购物车(混合,需两者共存)
- 避免使用 URL 全量字符串作键:它易携带噪声参数,且无法体现语义意图
边界校验与自动化保障
光靠人工约定容易出错。可在代码中嵌入轻量级校验逻辑:
- 定义接口元数据:标注每个端点是 static、per-user 还是 per-session
- 键生成器自动注入维度:根据元数据决定是否添加 user_id、tenant_id 等字段
- 日志中记录缓存键生成过程,便于排查“本该不同却命中同一缓存”的问题
- 在测试阶段用脚本扫描所有 API,检查是否存在未区分用户却共享缓存键的情况


















