现场是这样的。Ubuntu 20.04 上 PHP 8.1 配 opcache,发布脚本每次上线都 touch 一遍全部文件,之后 opcache_get_status 里命中率显示 0,接口响应反而比没开缓存时更慢,CPU 使用率明显上升。
中间走过弯路,把「opcache.memory_consumption 太小,缓存装不下就反复清空重来」当成主因,改完现象没变。
排查方向其实有限,先把可能性排一排。validate_timestamps 开着且 revalidate_freq 是 0,每个请求都要 stat 一遍脚本文件;发布时批量 touch 让所有文件的修改时间全变,整块缓存一次性失效;命令行和 FPM 用的是两份独立缓存,在命令行里看到的命中率不能代表线上。
直接读 FPM 那份缓存的统计
php -r 'var_dump(opcache_get_status(false)["opcache_statistics"]["opcache_hit_rate"]);'
然后确认校验相关参数的当前值
grep -E '^opcache\.(validate_timestamps|revalidate_freq|memory_consumption)' /etc/php/8.1/fpm/php.ini
再往下关掉时间戳校验,改由发布流程主动重置
sed -i 's/^opcache.validate_timestamps.*/opcache.validate_timestamps=0/' /etc/php/8.1/fpm/php.ini && systemctl reload php8.1-fpm
发布后显式重置一次缓存再看命中率
kill -USR2 $(pidof php-fpm | awk '{print $1}') && php -r 'var_dump(opcache_get_status(false)["opcache_statistics"]["opcache_hit_rate"]);'
恢复的判定其实很直接。命中率稳定在百分之九十九以上,opcache_statistics 里 misses 增速接近零,接口 p99 比故障时下降一半,CPU 使用率回到常态。
关掉校验后改代码必须靠 reload 或 USR2 生效,发布脚本里漏了这一步就会出现改了没反应。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
