Opcache
一、为什么需要 OPcache
PHP 是脚本语言,每次请求默认都要走完整流程:
1 | .php 源码 → 词法分析(Lexer) → 语法分析(Parser) → 编译(Compiler) → opcode → Zend VM 执行 |
在没有缓存的情况下,只有最后一步是真正在做业务,前面四步每个请求都重复跑一遍 —— 极其浪费。
OPcache 把编译产物(opcode)缓存在共享内存(SHM)里,下次同一个文件请求直接从内存拿编译好的 opcode 给 Zend VM 执行,跳过前四步。
性能提升:典型业务 QPS 提升 2-3 倍,CPU 使用率显著下降。PHP 5.5 起内置,开箱可用。
二、工作原理
1 | 请求 1:/index.php |
缓存 key:通常是脚本的完整路径 + mtime。文件改了 mtime 变了,缓存自动失效(validate_timestamps=1 时)。
存储:mmap 出来的共享内存段,所有 PHP-FPM worker 进程共享,无需重复缓存。
三、生产环境推荐配置
php.ini 关键参数:
1 | [opcache] |
开发环境差异
1 | opcache.validate_timestamps=1 ; 改了文件立即生效 |
四、validate_timestamps=0 的部署陷阱
生产环境为了省 stat 系统调用,通常设 validate_timestamps=0。带来的问题:你部署了新代码,OPcache 还在用旧的 opcode,新代码不生效。
3 种解法:
| 方案 | 做法 | 适用场景 |
|---|---|---|
| 重启 FPM | systemctl reload php-fpm | 简单,但有短暂中断 |
| 运行时 reset | opcache_reset() 或 cachetool opcache:reset --fcgi=... | 无中断,需要触发机制 |
| 原子部署 | 部署到新目录,软链切换 + reset | 大型项目最稳 |
推荐 cachetool:
1 | cachetool opcache:reset --fcgi=/var/run/php-fpm.sock |
五、监控与状态
CLI 看状态
1 | php -i | grep opcache |
运行时看状态
1 |
|
关键指标:
1 | hits # 命中次数 |
可视化面板
- opcache-gui:一个 PHP 文件,扔到 web 目录就能看
- opcache-status:Rasmus Lerdorf(PHP 之父)写的轻量版
六、常见问题
Q: OPcache 和 APCu 冲突吗?
A: 不冲突。OPcache 缓存 opcode,APCu 缓存用户数据(key-value),各管各的。
Q: 用了 OPcache,注解还能用吗?
A: 必须 opcache.save_comments=1,否则 Doctrine、Symfony、Swagger 等基于注解的框架会全部失效。
Q: PHP 8 的 JIT 值得开吗?
A: 看场景。纯 Web 业务(数据库 + 渲染)提升 < 5%,因为瓶颈在 IO;计算密集(图像处理、数学运算)能提升 30%+。先压测再决定。
Q: 为什么 opcache.max_accelerated_files 推荐质数?
A: OPcache 内部用哈希表存缓存,质数能减少哈希冲突。常用值:16229 / 20011 / 32531 / 65407。




