fastcgi_cache_lock的核心作用是控制缓存未命中时的并发穿透行为:仅首个请求穿透至php,其余请求阻塞等待5秒(不可配置),待缓存生成后统一返回;需配合fastcgi_read_timeout、fastcgi_cache_valid和fastcgi_cache_use_stale updating才能生效。

fastcgi_cache_lock 在高并发下保护后端,核心不是“锁住所有请求”,而是让多个并发请求对同一个未缓存 URL 的访问,只放行第一个去 PHP,其余排队等结果,避免瞬间大量穿透。它不提升单个请求速度,但能大幅降低后端瞬时压力——前提是配置得当,且后端响应够快。
✅ fastcgi_cache_lock 怎么起作用
- 多个用户同时访问
/article/123(该页面尚未缓存或已过期) - Nginx 检测到 cache miss,启用 lock 后:
- 仅首个请求发往 PHP-FPM 执行并生成响应
- 其余请求在 Nginx 内存中阻塞等待,不发往后端
- 首个请求返回、写入缓存后,所有等待请求统一从缓存读取并返回
- 这个等待有硬性上限:固定 5 秒,不可修改。超时后,等待请求放弃排队,各自回源(此时才可能打垮后端)
⚙️ 必须协同调优的三项关键配置
只开 fastcgi_cache_lock on; 是无效的,必须和以下参数配合:
-
fastcgi_read_timeout要大于后端典型耗时- 若 PHP 平均响应 2 秒,设为
10s更稳妥;若导出接口需 25 秒,fastcgi_read_timeout至少设30s - 否则首个请求还没返回,Nginx 就中断连接 → 锁失效 → 所有等待请求全部回源
- 若 PHP 平均响应 2 秒,设为
-
fastcgi_cache_valid要避免集中过期- 不要全设成
fastcgi_cache_valid 200 10m; - 推荐分层设置:
- 首页:
fastcgi_cache_valid 200 15m; - 文章页:
fastcgi_cache_valid 200 30m; - 加随机扰动(如用
map或业务侧加秒级偏移),防雪崩式失效
- 首页:
- 不要全设成
-
fastcgi_cache_use_stale updating必须开启- 配置示例:
fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;
- 效果:当缓存即将过期、首个请求正在更新时,其他请求可直接返回旧缓存,不卡死也不全回源
- 配置示例:
? 什么时候不该开 fastcgi_cache_lock
- 后端存在明显慢接口(如报表导出、复杂搜索),且
fastcgi_read_timeout无法设得足够长 - 缓存 key 设计混乱(比如含
?t=123456789时间戳或utm_*参数),导致每个请求 key 都不同 → lock 完全失效,形同虚设 - 响应头未清理(如未加
fastcgi_ignore_headers Set-Cookie;),带Set-Cookie的响应默认不缓存 → 每次都是 miss,lock 无意义
? 如何验证是否生效
在 location 块中加入:
add_header X-Cache-Status $upstream_cache_status; add_header X-Cache-Lock $upstream_cache_lock;
- 初次访问未缓存页:
X-Cache-Status: MISS,X-Cache-Lock: 1 - 并发访问同一未缓存页:部分请求
X-Cache-Lock: 1(表示排队中),后续请求X-Cache-Status: HIT(说明已从缓存返回)
不复杂但容易忽略











