fastcgi_cache_background_update 通过 stale 回退、稳定 cache key 和后端轻量响应三者协同,实现过期缓存毫秒返回、后台静默刷新;必须启用 fastcgi_cache_use_stale updating 及完整错误兜底,cache key 需排除易变字段,后端应识别 x-updating:1 跳过非核心逻辑,并关闭 fastcgi_cache_lock。

fastcgi_cache_background_update 本身不降低延时,它让 Nginx 在缓存过期后“不卡用户、悄悄刷新”,真正降低的是用户感知的首包延迟——旧内容毫秒返回,新内容后台生成。
要让它起效,必须配齐三根支柱:stale 回退策略、稳定 cache key、后端轻量响应。缺一不可。
必须启用 fastcgi_cache_use_stale updating
这是整个机制的开关钥匙。
Nginx 默认遇到过期缓存会阻塞等待 PHP 重生成,只有明确告诉它“允许在更新中返回旧内容”,后台刷新才有意义:
- 写法要完整:
fastcgi_cache_use_stale updating error timeout http_500 http_502 http_503 http_504 - 仅写
updating不够,回源失败时无法兜底,用户仍可能卡住 - 没这行,哪怕开了
background_update,请求也会阻塞,后台子请求根本不会发出
cache key 必须稳定且可复现
后台刷新请求必须和前台命中的是同一个缓存项,否则刷到“别处”,用户永远看不到新内容:
- 推荐 key 模板:
fastcgi_cache_key "$scheme$request_method$host$request_uri"; - 避免混入易变字段:如时间戳、随机数、未清洗的 Cookie 或 session ID
- 若接口依赖用户身份,应确保该信息已固化进 URI 或参数(例如
/api/user/123?version=2),而非靠后端动态判断
后端需识别 X-Updating: 1 并跳过非核心逻辑
Nginx 后台刷新时会自动带上这个请求头,PHP 可据此做轻量响应:
- 检查
$_SERVER['HTTP_X_UPDATING'] === '1' - 跳过:审计日志、消息推送、权限二次校验、埋点统计等耗时操作
- 保留:数据库查询、模板渲染、JSON 组装等核心输出逻辑
- 切忌在刷新路径中依赖未登录态或临时 session,否则缓存易污染或返回空/错内容
关于 fastcgi_cache_lock 的取舍
- 开启 lock(
on):防止多个请求同时触发回源,但会阻塞后台刷新请求,使其无法及时发起 - 关闭 lock(
off):配合background_update + stale更合理——首个过期请求触发后台刷新,其余全部走 stale 返回,既防击穿又保异步
建议统一设为 fastcgi_cache_lock off;,把并发控制交给 stale 和 background_update 协同完成。
配置生效后,用户请求不再因缓存过期而排队等待 PHP,而是始终拿到已有缓存;刷新动作完全后台静默,业务无感。











