这类问题我又碰上了一次。PHP 7.4 加了 opcache 之后跑得很快,最近每天下午开始报 Unable to allocate memory for pool,opcache_get_status 里 interned_strings_usage 的 free 变成 0,只有重启 php-fpm 才恢复。
第一反应是「opcache.max_accelerated_files 偏小,缓存频繁淘汰又重填」,验证下来不成立。
排查方向其实有限,先把可能性排一排。opcache.interned_strings_buffer 只有默认的 8M,项目里字符串字面量太多;代码发布后 opcache 没重置,旧脚本占着字符串池不释放;validate_timestamps 开着,每次请求都重新检查文件时间戳。
第一件事是看 opcache 的实际使用情况
php -r 'print_r(opcache_get_status()["interned_strings_usage"]);'
接着把字符串池和文件数上限一起调大
grep -nE 'interned_strings_buffer|max_accelerated_files' /etc/php.d/10-opcache.ini
然后重启 fpm 让新配置生效
systemctl restart php-fpm && php -i | grep -i opcache
发布流程里补一次缓存重置
curl -s http://127.0.0.1/opcache_reset.php
这类改动我都写进变更记录,过两周再出问题时能对上号。
我习惯把每一步的执行时间和结果记在一边,后面复盘省事。
改完先别撤,确认这几项。opcache_get_status 里 interned_strings 的 free 还有三成以上,缓存命中率在 99% 左右,不再出现内存告警。
interned_strings_buffer 调大后要重启才生效,光 reload 不行;上线脚本里带一次 opcache_reset 比改大参数更省事。这类问题最好一次改到位,反复小改反而容易把原因搅混。
