缓存键决定了什么才算同一份内容
缓存是否安全,取决于系统把哪些请求视为相同。语言、查询参数和个性化数据都可能改变响应,也就可能改变缓存键。
向下阅读
缓存常被描述成“把结果保存一会儿”,但真正决定安全性的,是缓存如何判断两个请求可以共用一个结果。若它认为两次请求相同,就会把第一次得到的内容交给后一次请求。这个判断通常由缓存键完成。
最基本的缓存键会考虑请求方法和 URL。可如果响应还取决于语言、设备类型、查询条件或某个公开的功能开关,只比较 URL 就不够。中文页面被缓存后发给英文访客,或者一个筛选条件的结果被错误地复用于另一个条件,都是“缓存命中了,但命中错了”。
先列出会改变响应的输入
检查页面和接口时,可以把影响响应的因素列出来:路径、查询参数、必要的请求头、语言偏好,以及是否存在用户专属内容。然后逐项决定它们是否需要进入缓存键,或者该响应是否根本不应共享缓存。HTTP 的 Vary 可以声明部分请求头会改变响应,但它必须与 CDN 和应用实际采用的缓存策略一致。
语言尤其容易被忽略。如果服务器根据 Accept-Language 返回不同版本,就需要通过缓存配置把语言差异表达出来。另一个选择是使用明确的语言路径,例如 /en/... 和 /zh/...,让 URL 本身体现内容版本。无论使用哪种方式,都应保证服务端渲染、客户端切换与边缘缓存采用相同规则。
个性化响应要更谨慎
当响应依赖登录状态、个人设置或私人资料时,共享缓存可能把一位访客的内容交给另一位访客。把 Cookie 或身份信息简单加入公共缓存键,既可能造成大量低效的键,也不能代替正确的访问控制。对私人响应,明确禁止共享缓存通常比试图设计一个包含所有身份细节的公共缓存键更可靠。
还要把查询参数当作产品语义,而非装饰。如果 ?page=2 或 ?sort=recent 改变了内容,缓存就必须区分它们;如果跟踪参数不影响内容,则可以在规则明确后忽略它们。参数处理不统一,会造成不必要的缓存碎片,或者把不同结果误当作同一份内容。
用不同身份验证缓存规则
验证缓存时,不只要重复请求同一个 URL。应当改变语言、查询条件和登录状态,检查响应正文、缓存头与 CDN 命中状态是否符合预期。还要覆盖首次未命中、后续命中和内容更新后的失效过程。
缓存键是一份关于“内容身份”的声明。只要认真列出哪些输入会改变结果,就能在速度与正确性之间做出可解释的选择;而缓存行为也不再像偶然发生的优化。