← 返回首页

协商缓存 ETag 和 Last-Modified 的区别

ETag 和 Last-Modified 都是 HTTP 协商缓存中的验证器(Validator),用于让浏览器询问服务器"资源有没有变化"。它们的核心区别在于验证依据不同:一个基于内容,一个基于时间。


工作原理对比

Last-Modified / If-Modified-Since

  • 服务器响应时:在响应头中返回 Last-Modified: Wed, 18 Jun 2026 06:00:00 GMT,表示资源最后一次修改的时间。
  • 浏览器再次请求时:自动带上 If-Modified-Since,值为上次收到的 Last-Modified 时间。
  • 服务器比对:如果资源在此时间之后没有被修改,返回 304 Not Modified;否则返回 200 和新资源。

ETag / If-None-Match

  • 服务器响应时:在响应头中返回 ETag: "a3f2b1c",这是根据资源内容生成的唯一标识(通常是内容的哈希值)。
  • 浏览器再次请求时:自动带上 If-None-Match,值为上次收到的 ETag。
  • 服务器比对:如果当前资源的 ETag 与请求头中的值一致,说明内容未变,返回 304;否则返回 200 和新资源。

核心区别

对比维度 Last-Modified ETag
验证依据 时间戳(最后修改时间) 内容哈希(唯一标识符)
精度 秒级 任意精度(内容级)
优先级 较低(兜底方案) 更高(RFC 推荐优先使用)
性能开销 低(只需读取文件修改时间) 稍高(需计算内容哈希)
适用场景 静态文件、秒级精度足够的场景 动态内容、需要精确验证的场景

Last-Modified 的局限性

Last-Modified 存在几个明显的缺陷:

  • 精度只有秒级:如果文件在 1 秒内被修改了多次,Last-Modified 无法感知到这些变化,可能导致缓存验证不准确。- 内容未变但时间变了:比如 CI/CD 重新构建生成的文件,内容完全一样但修改时间不同,会导致浏览器误判为"已修改",重新下载资源。- 无法处理某些特殊情况:有些服务器可能无法准确获取文件的最后修改时间。

ETag 的优势

  • 基于内容,更精确:只要内容有一个字节的变化,ETag 就会不同,不存在精度问题。- 强 ETag 与弱 ETag:ETag 分为两种:
    • 强 ETag(如 "a3f2b1c"):内容的任何变化都会导致 ETag 变化,适用于要求字节级一致的场景。
    • 弱 ETag(如 W/"a3f2b1c"):只有内容发生"重大变化"时才变化,适用于缓存场景中对细微差异不敏感的情况。

实际使用建议

  • 两者同时使用:RFC 9110 推荐同时返回 ETag 和 Last-Modified,以获得最佳的缓存覆盖效果。
  • ETag 优先级更高:当两者同时存在时,服务器通常优先比对 ETag,Last-Modified 作为兜底。- 负载均衡场景注意:在多台服务器的负载均衡环境中,需要确保各服务器对同一资源生成相同的 ETag,否则会导致缓存失效。