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

fastcgi_cache_lock 的核心作用不是“防止压垮”,而是控制缓存未命中时的并发穿透行为——它让多个请求在缓存失效瞬间不一起打到 PHP,而是排队等第一个请求生成缓存,其余请求稍后直接读缓存。这能显著降低后端瞬时压力,但前提是配置得当、超时合理、协同参数匹配。
✅ fastcgi_cache_lock on 是怎么起作用的?
- 当多个请求同时访问一个尚未缓存(或已过期)的 URL 时:
- 只有第一个请求穿透到 PHP-FPM 执行;
- 其余请求在 Nginx 层阻塞等待,而不是立刻失败或重试;
- 等第一个请求返回并写入缓存后,所有等待请求统一从缓存取结果返回。
- 这个“等待”有硬性上限:固定为 5 秒,不可修改(Nginx 源码写死,无
fastcgi_cache_lock_timeout指令)。
⚙️ 必须配合调优的关键参数
仅开 fastcgi_cache_lock on 不够,必须和以下三项对齐,否则等待会变成“假排队+真断连”:
fastcgi_read_timeout≥ 后端 PHP 最长合理耗时
比如 PHP 导出报表要 20 秒,fastcgi_read_timeout至少设为25s;否则第一个请求还没回,Nginx 就先超时中断,导致锁释放失败、后续请求全部穿透。-
fastcgi_cache_valid设置合理过期时间
避免大量缓存项在同一秒过期(集中失效)。建议:- 主页/列表页:
fastcgi_cache_valid 200 15m; - 加随机偏移(靠
inactive或业务层加时间扰动),或用map分层设置不同 TTL。
- 主页/列表页:
-
fastcgi_cache_use_stale updating必须开启
让等待中的请求在锁生效期间也能返回旧缓存(而非干等或失败):fastcgi_cache_use_stale updating error timeout http_500 http_503;
这样即使第一个请求慢,其他请求也不卡死,用户体验更稳。
? 常见误操作及后果
- 把
fastcgi_cache_lock_timeout 30s;写进配置 → Nginx 启动失败或静默忽略(该指令根本不存在); -
fastcgi_read_timeout设太短(如5s),而 PHP 平均响应8s→ 第一个请求总超时,锁反复释放,大量请求穿透,比不开锁还糟; - 关闭
fastcgi_cache_lock却没做其他保护 → 高并发缓存失效时,所有请求直击 PHP,瞬间打满pm.max_children,出现 502/连接拒绝。
? 上线前检查清单
- 用
curl -I多次请求同一未缓存 URL,观察:- 第一次:
X-FastCGI-Cache: MISS - 第二、三次(5 秒内):
X-FastCGI-Cache: HIT或STALE(说明锁+stale 生效)
- 第一次:
- 查 Nginx error 日志,确认无
upstream timed out或cache lock failed类报错; - 压测时监控 PHP-FPM 的
slowlog和status页面,确认并发请求数未突破max children。
不复杂但容易忽略
立即学习“PHP免费学习笔记(深入)”;



















