动态价格接口需服务端精准识别变更并打破缓存链条,推荐版本化url(如/api/price/item-123?v=20240520143022)或主动失效缓存(redis del/cdn purge),辅以etag协商与短ttl预热兜底。

动态价格接口需要在价格变更时立即生效,不能依赖缓存过期等待,因此必须主动“绕过缓存”或“失效旧缓存”。这不是单纯加个 Cache-Control: no-cache 就能解决的——那只是让客户端重新校验,后端仍可能返回缓存值。真正有效的缓存绕过,核心在于**服务端精准识别变更并打破缓存链条**。
用版本化 URL 或查询参数强制刷新缓存
最直接可控的方式:把价格数据的唯一标识(如商品 ID + 最新更新时间戳、版本号、hash)嵌入请求路径或 query 中。缓存系统(CDN、反向代理、网关)会将带不同参数的 URL 视为不同资源,天然不复用旧缓存。
- ✅ 推荐格式:
/api/price/item-123?v=20240520143022或/api/price/item-123?_t=1716215422 - ✅ 后端在价格更新时生成新版本标识(如 MySQL 更新后触发写入 Redis 的 version key),前端拉取价格前先查最新版本,拼出新 URL 发起请求
- ⚠️ 注意:避免用用户态参数(如
?uid=xxx)做缓存键,否则导致缓存碎片;应只用业务强相关、低频变更的维度
服务端主动失效缓存(Purge / Invalidate)
当价格更新事件发生(例如管理后台提交、库存服务回调、定时任务刷新),后端同步清除对应缓存项。适用于使用 Redis、Memcached 或支持 purge 的 CDN(如 Cloudflare、阿里云全站加速)。
- ✅ 对 Redis:执行
DEL price:item-123或用前缀批量删(KEYS price:item-*需谨慎,建议用 SCAN + DEL 或设置带前缀的 namespace) - ✅ 对 CDN:调用 API 发送 PURGE 请求(如
PURGE https://api.example.com/api/price/item-123),部分平台支持按 tag 失效(如X-Cache-Tag: price-item-123) - ⚠️ 关键点:失效操作必须与数据库写入在同一事务边界(或至少强最终一致),避免出现「已删缓存但 DB 写失败」的脏状态
响应头配合 ETag + If-None-Match 实现条件式绕过
适合对缓存友好性要求高、且能接受少量协商开销的场景。服务端为每个价格响应生成唯一 ETag(如 ETag: "xyz789",内容可基于 price + updated_at 的 hash),客户端携带 If-None-Match 发起请求。
- ✅ 若价格未变,服务端返回
304 Not Modified,不走业务逻辑,极轻量 - ✅ 若价格已变,服务端正常返回
200+ 新数据 + 新 ETag,自然绕过旧缓存 - ⚠️ 前提是客户端(App / H5)真实实现了 ETag 缓存逻辑;浏览器默认支持,但原生 HTTP 客户端或某些 SDK 可能忽略
兜底策略:短 TTL + 高频主动预热
当无法精确控制失效或版本化成本过高时,可用“短生存期 + 变更后立即刷新”组合降低风险。
- ✅ 设置缓存 TTL 为 1–5 秒(如
Cache-Control: public, max-age=2),牺牲一点性能换取强时效性 - ✅ 价格变更后,主动向缓存写入新值(cache-aside 模式),同时触发一次“预热请求”打到边缘节点,确保热门商品缓存尽快更新
- ⚠️ 需监控缓存命中率和回源 QPS,防止 TTL 过短引发后端雪崩











