OPcache内存耗尽典型表现为响应变慢、CPU突增、used_memory_percent长期>95%及“Cache full”日志;根本原因是共享内存池填满导致频繁重编译,应合理设置memory_consumption(64~128MB)、jit_buffer_size(≤50% memory_consumption),禁用validate_timestamps,配合部署清缓存,并清理file_cache旧目录。

OPcache 内存耗尽的典型表现
不是报错,而是请求响应变慢、CPU 突增、opcache_get_status() 显示 memory_usage.used_memory_percent 长期 >95%,甚至反复出现 “Cache full” 日志。这不是缓存“过期”,是共享内存池真被填满了——新脚本进不去,旧脚本又被频繁淘汰,导致大量重编译,性能断崖式下跌。
别只调大 opcache.memory_consumption
盲目加到 256MB 或 512MB 在低配机(如 1GB 内存)上反而危险:FPM worker 进程会为每个请求预留 OPcache 共享内存段,实际占用远超配置值;且大内存池会加剧哈希冲突,降低命中率。更关键的是,PHP 8.4 的 JIT 缓冲区(opcache.jit_buffer_size)也从同一块共享内存里切分,挤占过多会导致 JIT 直接失效。
-
opcache.memory_consumption建议设为64~128(单位 MB),够用即可 - 必须同步设置
opcache.jit_buffer_size=32M或64M,且确保它 ≤opcache.memory_consumption的 50% - 删掉
opcache.max_wasted_percentage的自定义值(默认 5% 即可),改高反而让碎片积累更隐蔽
精准控制缓存“进”与“出”的节奏
满的根本原因是“进得多、出得乱”。PHP 8.4 默认不主动淘汰冷门脚本,全靠 LRU + 内存压力触发,不可控。要手动干预:
- 关掉运行时校验:
opcache.validate_timestamps=0(上线后必须关),否则每次stat()都可能触发隐式重编译 - 把
opcache.revalidate_freq改成0(配合上一条,彻底禁用自动检查) - 用部署流程代替“等它满”:
git pull后立即执行opcache_reset(),或通过宝塔/CI 脚本调用curl -s http://localhost/clear-opcache.php?token=xxx - 避免缓存无用文件:在
opcache.blacklist_filename中明确排除日志、临时目录、调试文件(如*debug*.php,/tmp/*.php)
file_cache 模式下旧目录堆积才是真隐患
如果你启用了 opcache.file_cache_only=1,/path/.opcache 下一堆时间戳命名的子目录(如 20261001123456)才是真正吃 inode 和磁盘 I/O 的元凶——它们不会被 OPcache 自动清理,但又长期闲置。
立即学习“PHP免费学习笔记(深入)”;
- 写个轻量脚本(比如
/path/.opcache/clean-old.php),只保留最新 2 个目录:ls -t /path/.opcache | tail -n +3 | xargs -r rm -rf - 加到 crontab 每天执行一次:
0 3 * * * /usr/bin/php /path/.opcache/clean-old.php - 确认
opcache.file_cache路径有写权限,且该路径不在 Web 可访问范围内(防止暴露)
真正卡顿的从来不是 OPcache “要不要缓存”,而是“缓什么、留多久、谁来清”。PHP 8.4 的 JIT 和新优化器很猛,但前提是别让它在内存碎片和旧缓存文件里打转。



















