← 返回首页
协商缓存 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"):只有内容发生"重大变化"时才变化,适用于缓存场景中对细微差异不敏感的情况。
- 强 ETag(如
实际使用建议
- 两者同时使用:RFC 9110 推荐同时返回
ETag和Last-Modified,以获得最佳的缓存覆盖效果。 - ETag 优先级更高:当两者同时存在时,服务器通常优先比对
ETag,Last-Modified作为兜底。- 负载均衡场景注意:在多台服务器的负载均衡环境中,需要确保各服务器对同一资源生成相同的ETag,否则会导致缓存失效。