动静分离架构中,缓存过期策略与强制刷新是保障用户体验和系统稳定性的关键,核心在于区分静态资源与动态请求的不同缓存逻辑,并通过版本号、CDN API等手段在必要时主动失效缓存。
缓存过期的本质:不同资源要区别对待
所有缓存过期策略都在做同一件事:在数据新鲜度和系统负载之间找平衡点,静态资源(图片、CSS、JS)和动态接口(用户信息、订单状态)对缓存的要求截然不同,混在一起用一套规则,结果往往是灾难性的。
静态资源过期策略:文章页与图片的分层处理
动静分离后,CSS和JS这类构建产物通常会带上内容哈希(如app.8f3k2d.css),文件名变了旧缓存自然失效,但文章页面的HTML片段、用户头像这类带业务属性但更新频率低的资源,需要一个合理的TTL(生存时间)。
- 带哈希的构建资源:设置长期缓存,TTL建议7-30天,配合CDN的
immutable标志,型HTML页面:TTL控制在5-15分钟,既减轻源站压力,又有一定实时性。 - 用户头像、商品图缩略图:TTL设为24小时,变化不频繁但也不能永久缓存。
行业共识认为,绝大多数中小站点把静态资源TTL设置在15分钟到24小时的范围,就能解决80%以上的回源请求压力,同时不会在内容更新时出现大面积旧数据问题,据工信部近年的公开信息,国内主流云服务商CDN产品的默认静态缓存时长也落在这一区间。
动态接口不要走普通缓存通道
动态接口缓存一直是动静态分离最不好处理的环节,不少运维图省事,给/api/user/info这类地址也套上统一缓存规则,结果用户改了头像、绑定手机号后半天看不到变化,只能靠强制刷新硬扛,体验很差。
正确的思路是:用户身份相关的请求默认不缓存,直接透传到源站,只有非个性化的公共接口(比如文章列表、省份城市数据)才做短TTL缓存,一般设置为1-3分钟,用Vary: Cookie或Cache-Control: private标记区分。
缓存强制刷新的三种落地路径
缓存策略是日常维护用的,强制刷新则是应急治理手段,当内容被错误缓存、上线后发现BUG、数据被恶意污染时,需要有办法快速“挖掉”缓存,三种常见方案各有用武之地。
CDN服务商提供的刷新/预热API
各云厂商控制台都提供“刷新缓存”功能,也开放了API,操作路径通常是:CDN控制台 → 刷新预热 → URL/目录刷新。
- URL刷新:针对单个具体文件名,秒级生效,适合精准清除一个页面。
- 目录刷新:清除某个目录前缀下所有缓存,适合大范围更新,但要注意,目录刷新操作成本较高,不当使用会造成瞬间回源高峰,可能直接压垮源站。
实操时有一点值得留意:刷新API调用结果异步返回,别以为提交成功就立刻生效,大多数CDN的刷新生效时间在1-3分钟内,高峰期可能更长,有紧急需求时务必提前操作。
Nginx层实现的可控缓存旁路
很多场景没办法依赖CDN(比如内网系统、私有化部署),这时Nginx的proxy_cache模块可以配合特殊Header实现手动控制。
proxy_cache_bypass $arg_bypass;
proxy_cache_purge $arg_purge;
通过在请求URL里加参数触发旁路:curl https://站点.com/article/123?bypass=1,Nginx就不查询缓存直接回源拉取最新数据,同时可以用proxy_cache_purge模块精准删除某条缓存记录,这种方式灵活度高,权限控制在自己手里,适合有技术储备的团队,但要记得在生产环境通过鉴权保护这些操作,否则被恶意刷?purge=1,缓存会全线崩溃。
静态文件版本号与文件名双保险
最实用、也最经常被忽略的强制刷新手段,是改变资源标识,适用于所有场景,不需要额外系统支持。
- 构建文件名:
webpack.dll.js→webpack.dll.3j28d9.js - URL参数版本号:
/static/common.css?v=220715(适用于无哈希的产物) - HTML引用处统一维护版本变量,修改一处全站更新
常见误区是只改文件名或参数,但HTML页面本身的缓存TTL太长,导致引用链接没有及时更新,建议HTML首页设置不缓存或极短缓存(不超过60秒),内页保持较短TTL,这样改文件名的效果就能在合理时间内全站生效。
上线期间的缓存治理策略
发布新版本是最容易触发缓存事故的时间窗口,常规做法是先改缓存层策略,再发业务代码。
合理编排:先缩TTL,再发版本,后恢复
一个标准的上线流程可以参考:
- 上线前10分钟,将CDN和Nginx的动态页面缓存TTL临时调整为60秒。
- 部署新代码,跑冒烟测试(此时回源频率略高但可接受)。
- 验证无误后,执行一次全站或受限目录的缓存刷新,清掉可能残留的旧数据。
- 观察10分钟,流量曲线稳定后,把TTL恢复到常规水平。
这个流程不需要额外开发,所有粗粒度CDN基本都支持在线修改,对于无法临时调TTL的自建系统,多半只能依赖刷URL脚本,但批量操作时注意控制并发,打满回源会触发源站防护策略。
公共数据缓存被污染时的应急处理
数据被篡改并缓存在边缘节点时,常规TTL无法解决问题,业内专家指出,这种场景的核心原则是:先断动态源,再清静态缓存。
操作路径:源站接入层临时把异常接口的响应码强制改为503 → 触发CDN的默认缓存错误逻辑(大多数CDN对5xx响应默认不缓存) → 对涉及URL做刷新 → 修复数据 → 恢复源站,这套流程能有效撑过去,且能避免被边缘错误缓存长期覆盖。
别忘了用户端的缓存叠加问题
服务器和CDN的缓存搞定后,浏览器本地缓存也是一个“隐形毒瘤”,强制刷新服务器的缓存,只是保证了边缘节点拿到的是新数据,但如果用户浏览器本地缓存了旧文件,依然会访问到旧资源。
- 常规强制刷新(Win: Ctrl+F5 / Mac: Cmd+Shift+R)会忽略本地缓存全部重新拉取,但要求用户手动操作。
- 更聪明的办法:在静态资源引用的URL上打时间戳(如
?v=202603281030),前端发版时自动更新,这样不用用户操作,浏览器自己发现URL变了就会重新拉取。 - JS和CSS需要分开处理:HTML全部不缓存;JS、CSS采用内容哈希;图片等大体积依赖CDN的刷新接口。
常见问题精讲
动静分离缓存过期策略怎么设置?
判断标准有三条:资源是否会变、变化频率多高、用户能接受多长的滞后,构建产物带哈希设长期缓存;接口和页面依据业务容忍度设置短TTL;身份相关动态请求关闭缓存,多数情况下,把TTL分成“永久、1小时、10分钟、0”四档就覆盖所有业务场景了。
动静分离强制刷新缓存后,源站压力突然飙高正常吗?
正常,强制刷新相当于把边缘节点存储的那部分请求压力重新传导到源站,设想拥有100个边缘节点,一次全国范围的强制刷新,每个节点回源请求都会进来,为降低这种冲击,建议分批刷新目录,或先扩容源站带宽和CPU资源,等回源流量过去后再缩容恢复。
网站做了动静分离,为什么CSS样式更新后用户看到旧页面?
大概率是HTML入口文件本身被缓存了,或者CDN边缘节点的缓存没有在预期时间内失效,检查CDN刷新记录是否生效(在CDN界面的操作记录里一般可以看到),再确认源头Web服务器的缓存控制头是否设置正确(Cache-Control: no-cache对HTML,max-age对带哈希的静态资源),这两个点检查到位,基本能覆盖这一类问题。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/795195.html


