我把91网页版的缓存管理拆给你看:其实一点都不玄学(真的不夸张)

前言 这篇文章是一次“拆机式”的讲解:不卖关子、不讲大道理,直接带你从浏览器、服务端到 CDN,把一个高流量站点常见的缓存体系逐层拆开看清楚。读完能做到两件事:一是自己能快速诊断页面“为什么没更新/为什么老是走网络”;二是能给出实际可执行的优化项,让缓存既省带宽又不把内容缓存错位。
开篇一问:什么是我们要解决的痛点?
- 页面或资源更新后用户看不到最新内容(缓存不命中或太久);
- 静态资源频繁请求增加带宽和延迟;
- 登录/付费等受保护资源又不能被误缓存;
- 部署或发布时需要快速清理缓存而不影响在线用户体验。
整体缓存分层(从客户端到边缘)
- 浏览器缓存:Cache-Control、ETag、Expires、Service Worker、IndexedDB/LocalStorage(不严格算HTTP缓存但常用于离线)。
- 反向代理/缓存层:Nginx、Varnish、Squid,在源站前做边缘缓存。
- CDN(边缘节点):Akama i、Cloudflare、Fastly 等,会有各自的缓存控制与统计。
- 中间层/应用级缓存:Redis、Memcached(常用于动态渲染结果或 API 响应缓存)。
- 客户端应用层缓存:前端框架的内存缓存、Service Worker 的 Cache Storage。
如何快速“拆”出当前缓存策略(工具与步骤) 1) 用浏览器 DevTools(Network / Application)
- 查看请求响应头(Cache-Control、ETag、Expires、Vary、Age、x-cache 等)。
- Application → Service Workers、Cache Storage,看有没有 SW 在拦截请求。
- Network 面板右键选择 “Disable cache” 做对比测试。
2) 命令行工具抓包 / 查看头
- curl -I https://example.com/page.html
- curl -s -D - https://example.com/asset.js -o /dev/null 关注 Cache-Control, ETag, Last-Modified, Age, Via, X-Cache、X-Cache-Hits 等。
3) 通过 CDN/边缘特征判断命中情况
- 响应头常带 x-cache: HIT/MISS、Age 秒数,或 Via、CF-Cache-Status(Cloudflare)。
- 可以在不同地理位置测试,或者通过 curl + --resolve 指向不同节点看差异。
4) 模拟发布 / 缓存失效流程
- 更新静态文件后更换文件名(content-hash)并观察浏览器是否拉取新文件。
- 不改名只改内容,看看是否因为 ETag/Last-Modified 而更新或仍然走缓存。
常见响应头组合与推荐策略(实用范例)
-
静态资源(js/css/img):
-
Cache-Control: public, max-age=31536000, immutable
-
结合文件名 content-hash(app.abc123.js)
-
说明:用长缓存+hash 可以让 CDN/浏览器长期缓存,只有文件名变更才刷新。
-
HTML 页面(需要频繁更新或个性化):
-
Cache-Control: no-cache, must-revalidate
-
或短期缓存:Cache-Control: public, max-age=60, stale-while-revalidate=30
-
说明:no-cache 意味着浏览器会回源校验(通过 If-None-Match),适合需要确认最新内容的页面。stale-while-revalidate 可减少响应延迟并在后台更新。
-
API/动态接口(需鉴权或个性化):
-
Cache-Control: private, max-age=0, no-store(敏感数据)
-
对于可缓存的公共API:Cache-Control: public, max-age=60
-
ETag vs Last-Modified
-
ETag 更精准(基于内容指纹),Last-Modified 有时受服务器时间影响。两者可以同时提供,浏览器会优先 If-None-Match。
Service Worker 的使用与注意点
- 常见策略:Cache First(适合静态资源)、Network First(适合 HTML 或需要最新数据的内容)、Stale-While-Revalidate(体验与实时性的折中)。
- 要点:
- SW 范围(scope)要设置合理,避免把登录页/敏感路径纳入长期缓存范围。
- 更新 SW 时做好版本控制,避免旧 SW 与新资源冲突。
- Cache Storage 容量和清理策略需要考虑浏览器限额,避免无限制地把大文件缓存到客户端。
缓存失效(Cache Busting)实战方法
- 文件名指纹(content hash)是最可靠的做法:把版本控制交给构建工具。
- 对于不能改名的资源,用查询字符串 ?v=20260220,但注意部分 CDN/代理可能忽视 query。
- 发布钩子触发 CDN 清理(API 调用或自动化脚本),避免手动操作。
边缘/中间层缓存策略(CDN、Nginx、Varnish)
- 在 CDN 层做静态资源缓存,缓存 HTML 时要非常小心:
- HTML 对于不同用户可能有差异,使用缓存键(cookie、Authorization)或按路径细分。
- 对于需要缓存的 HTML,可用缓存变体(Vary、cache key)并设置合理 TTL。
- 缓存穿透与缓存击穿:
- 缓存击穿:高并发下某个热点失效时大量请求回源。常用互斥锁(singleflight)、短 TTL 与预热、或用“临时兜底缓存”避免回源洪峰。
- 缓存穿透:恶意/异常的随机请求一直命中未缓存资源。用请求限制、布隆过滤器或在 CDN 层做黑名单过滤。
安全与隐私考量(尤其对成人站点或含敏感数据的站点)
- 登录态/受限内容不要放到公共缓存(CDN 节点)或浏览器持久缓存中。
- 对含敏感信息的响应设置 Cache-Control: private 或 no-store。
- 如果必须通过 CDN 提速受保护资源,使用带签名 URL 或短期凭证,结合边缘鉴权。
监控与验证(不可忽略)
- 在部署后观察:Cache Hit Ratio(CDN/Proxy)、origin bandwidth、edge latency、ErrorRate。
- 用 Chrome Lighthouse / WebPageTest 检查缓存带来的性能改进。
- 打点日志:在响应中临时添加 x-debug-info(如缓存命中来源),在一段时间后移除。
常见错误与排查技巧(速查)
- “资源没更新”:
- 检查响应头是否有长 TTL;
- 检查是否存在 Service Worker 在拦截并返回旧缓存;
- 检查 CDN 还没 purge;
- 检查是否用了 immutable 且文件名不变。
- “敏感页被缓存到 CDN”:
- 查看响应头是否 public 或缺少 Authorization 控制;
- 查看 CDN 配置是否将该路径设为可缓存。
- “部署后用户看到旧内容但开发者看到了新内容”:
- 开发者本地可能有禁用缓存或特殊 header,真实用户走 CDN/edge 缓存。
落地清单(可以直接照做)
- 静态资源:构建输出带 content-hash,Cache-Control: public, max-age=31536000, immutable。
- HTML:除非必须长期缓存,用短 TTL 或 no-cache,结合 stale-while-revalidate 提升体验。
- API:分离公共缓存与私有缓存,私有内容设置 private/no-store。
- Service Worker:定义清晰的 scope 和版本更新流程,做好 Cache Storage 的清理策略。
- 部署:打包后通过 CI 自动触发 CDN 差异或 purge 接口;把关键变更列入发布说明并在监控中观察缓存相关指标。
- 监控:设置 CDN 命中率告警、origin 带宽告警与页面加载时长基线。
结语(搬砖式总结) 缓存不是玄学,而是多层权衡:带宽 vs 时效、命中率 vs 正确性、体验 vs 隐私。把每一层都看清楚、定位好边界、并用自动化把发布与清理串联起来,体验和成本都会顺滑很多。希望这篇“拆给你看”的内容能帮你把手头站点的缓存状况摸清楚并落地优化。
想要我亲自替你把站点拆一遍、做一份“缓存健康诊断报告”并给出可执行的改进清单?留下页面地址和目标(提高命中率/降低带宽/缩短冷启动时间),我来帮你把复杂的缓存体系变成一份清晰的工程计划。

















![[爆料]糖心vlog突发:大V在今日凌晨被曝曾参与丑闻,窒息席卷全网](https://wap.shenma-1.com/zb_users/upload/2025/09/20250922154946175852738694263.jpeg)


