关于91网,我把缓存管理讲清楚后,很多问题都通了

引言 近日在优化91网的过程中,我把整套缓存体系从头梳理并明确了管理规则,结果很多长期困扰我们的问题迎刃而解——页面不一致、峰值时源站奔溃、静态资源更新慢、调试上线频繁互相影响等。下面把我整理的方法和实战细节写出来,便于复用和传播,也方便你直接在网站上发布、收藏或分享给团队。
缓存基础:先把概念讲清楚
- 缓存层级:浏览器缓存(client)、CDN(edge)、反向代理(如Nginx/Varnish)、应用内缓存(内存/Redis)、数据库缓存。每层都有不同的粒度、TTL和失效方式。
- 两种基本策略:强制缓存(Cache-Control: max-age、immutable、Expires)和协商缓存(ETag、Last-Modified + 304)。
- 缓存键(cache key):决定相同请求是否命中缓存。通常基于 URL、查询参数、Host、Headers、Cookies 等构成。CDN/代理一般允许自定义。
- 缓存失效:主动(Purge/Surrogate-Key)和被动(TTL 到期、协商校验)。主动失效要靠接口和体系支持,被动失效要靠合理的 TTL 和 revalidation 策略。
我们之前遇到的典型问题(列举现实场景)
- 页面A上线后,部分用户还能看到旧版本,刷新也不稳定(浏览器+CDN缓存配置冲突)。
- 高并发促销时段,源站瞬间被击穿(缓存未覆盖热点或缓存失效策略不当)。
- 静态资源更新需要改名或手动清理多层缓存,流程复杂易出错。
- 针对用户登录态或个性化内容,缓存策略混淆导致敏感数据被缓存到公共层。
- CDN配置里忽略了某些Header或Cookie,导致资源缓存分散、命中率低。
我采取的逐步方法(落地可操作) 1) 全面审计(从“现状”开始)
- 用 curl -I、浏览器 DevTools、CDN 控制台和访问日志记录每个资源的响应头(Cache-Control, ETag, Age, Via 等)。
- 列出所有可能被缓存的路径和页面,标注“是否可缓存”“缓存等级(静态/半静态/动态)”“失效时机”。
2) 按资源波动性分类并定义策略
- 静态资源(图片、JS、CSS):采用文件名哈希(content hash),Cache-Control: public, max-age=31536000, immutable。
- 半静态(配置、模板):中等 TTL(几分钟到几小时),可使用 surrogate-keys 方便批量清理。
- 动态/个性化内容:不在公共 CDN 缓存或缓存短 TTL,使用边缘侧逻辑做差异化(Edge-side includes、Edge Workers)或基于用户标识的缓存键。
3) 统一并修正响应头
- 对静态资源强制:Cache-Control: public, max-age=31536000, immutable。
- 对可协商的资源:提供 ETag 或 Last-Modified,并结合合理的 max-age,避免每次都回源。
- 对敏感或绝对不能缓存的页面:Cache-Control: no-store, no-cache, must-revalidate(根据需要选择)。
4) 静态资源版本化(必须做)
- 构建时把内容哈希加入文件名(app.abc123.js)。上线时不再依赖清理缓存。
- 对 HTML 主文件和模板采用较短 TTL,并在部署流程中更新引用到新哈希的静态资源。
5) CDN 与缓存键的优化
- 确定缓存 key:对静态资源忽略 Cookie、Authorization;对需要区分 UA 或 Accept-Language 的资源把对应 Header 加入 key。
- 使用 CDN 的 surrogate-key/Tag 功能,按业务模块或路径打标,部署/回滚时可按 tag 批量清理。
- 设置分级缓存(edge + origin shield)减少 origin 压力。
6) 防止缓存雪崩与击穿
- 对高并发热点使用互斥锁、request coalescing、或设置随机化 TTL(TTL jitter)。
- 在缓存失效前使用 stale-while-revalidate,让边缘在回源时仍可返回旧内容,降低回源峰值。
- 对关键数据设置二级缓存(应用内 + CDN),并为后端设置降级逻辑。
7) 动态内容与个性化策略
- 对用户私有数据做 no-cache/no-store,或使用不同的缓存空间(按用户 token 做 key)并严格避免公开层缓存。
- 如果页面大部分是公共的、只有小块个性化,可采用 Edge Side Includes(ESI)或客户端异步请求个性化区域。
8) 自动化与运维流程
- 在 CI/CD 中加入缓存相关动作:静态资源哈希、部署后触发 CDN 刷新(按 tag),记录变更日志。
- 提供一键回滚或回源开关(当缓存逻辑出问题时能快速切换到“绕开缓存”的临时方案)。
监控与量化指标(不做监控就无法优化)
- 关键指标:缓存命中率、Origin 请求数、边缘带宽、P95/P50 页面加载时间、错误率。
- 告警规则:源站请求短时间暴增、缓存命中率急跌、特定资源 404/500 激增。
- 用 Grafana/Prometheus 或 CDN 自带 Analytics 做可视化,按业务维度分拆指标(首页、静态资源、API等)。
实战小例子(常用命令)
- 查看响应头:curl -I https://91.example.com/static/app.js
- 强检 header 示例:Cache-Control: public, max-age=31536000, immutable
- 协商缓存示例:ETag: "abc123", 当客户端下次请求带 If-None-Match 时,源站可返回 304。
常见症状与快速排查清单
- 症状:用户看不到最新内容 检查点:浏览器 DevTools Network 看是否有 304 / Age / Cache-Control;CDN 是否有旧对象;是否需静态资源哈希。
- 症状:高并发导致源站崩溃 检查点:缓存命中率、TTL 设置、是否有热点未被缓存、是否存在未处理的缓存击穿。
- 症状:个性化信息被错误缓存 检查点:响应是否含有 Set-Cookie 或 Authorization 被 CDN 纳入缓存 key;是否使用了 no-store。
- 症状:CDN 缓存分散、命中率低 检查点:缓存键是否包含不必要的 Header/Cookie/Query 参数,是否需要统一清理策略。
我在91网的效果(可量化改进示例)
- 缓存命中率从 30% 提升到 80% 以上(典型目标),源站请求量显著下降,峰值稳定许多。
- 首屏加载时间明显降低,用户体验提升,页面可用性在高并发时段稳定。
- 部署和回滚流程更清晰,静态资源无需每次手动清缓存,团队协作效率提高。
结语(给出可直接执行的下一步) 如果你正在为站点的“看不见的慢”和“不可靠的缓存”头疼,建议先做三件事:1)全面审计当前缓存头和 CDN 行为;2)把静态资源做哈希并设置长期缓存;3)为动态/个性化内容定义明确的缓存边界。按上面步骤逐条落实,你会发现系统稳定性和运维效率都能快速改观。