当前位置: 首页 > 后端技术 > PHP

关于PHPOpcache缓存刷新,代码过载

时间:2023-03-30 00:10:51 PHP

问题背景通过开启Opcache的缓存优化,将PHP代码预编译成Opcode缓存在共享内存中供进程重复调用,从而减少PHP代码从磁盘中重复解析的时间消耗,显着提升了PHP性能,提高了业务性能调用,但是也带来了一些问题,就是我们每次更新对应的PHP代码,web服务器无法实时加载更新的代码。解决方案(一)、设置Opcache脚本验证时间可以通过更改Opcache的以下两个配置选项来调整代码重载时间opcache.revalidate_freq=0检查脚本时间戳是否更新,单位秒。(如果设置为0,OPcache将检查每个请求的脚本更新)opcache.validate_timestamps=0如果启用,OPcache将每隔opcache.revalidate_freq秒检查一次脚本更新。PS:在实际生产环境中,为了尽可能达到最佳性能,尽量不要开启文件更新验证,因为每次验证都会将PHP代码重新编译到共享内存中。(2)重启|重载php-fpm进程每次重启或重启php-fpm进程都会重新解析PHP脚本文件,但是重启fpm进程可能会导致请求中断,导致写入脏数据或事务回滚等待一系列异常。重载比重启顺畅很多,不会造成用户请求直接中断。相对来说,风险要低很多。但是,当php-fpm收到一个reload信号时,它会向所有的子进程发送一个SIGGUIT信号,同时注册一个定时器。如果子进程没有在指定时间内退出,则发送SIGTERM信号结束子进程。如果子进程在一秒内仍然没有结束,则直接发送SIGKILL强制kill。重启php-fpmservicephp-fpmrestartreloadphp-fpmservicephp-fpmreloadorkill-USR2`cat/usr/local/php/var/run/php-fpm.pid`(3)、手动清空除上述之外的缓存有两种方式,还有一种更安全的缓存清理。我们可以通过opcache_reset()和opcache_invalidate()函数刷新Opcache缓存。opcache_reset()-重置整个Opcode缓存,所有PHP脚本将被重新解析并预编译到Opcode中。opcache_invalidate()-清除指定的脚本缓存,可以传两个参数,一个是刷新文件路径,一个是force字段,如果force没有设置或者传入的是FALSE,那么只有当修改时间的时候script比对应的Opcodetime更新,脚本的缓存将会失效。需要注意的是,当PHP以PHP-FPM模式运行时,opcache的缓存是无法通过php命令清除的,只能通过http或者cgi到php-fpm进程来清除。我们可以写一个External接口来达到清除缓存的目的。相关实现如下(框架:laravel):Route::any('cache-reset',function(){//重置整个Opcode缓存dd(opcache_reset());});Route::any('cache-update',function(){//清除最后更新文件的缓存exec('gitdiff--name-onlyHEAD~HEAD',$output);foreach($outputas$file){$path=base_path($file);opcache_invalidate($path,true);}dd('刷新完成');});总结以上三种策略,可以达到Opcache缓存更新的目的,但是在流量高峰期或者流量大的服务器,每次都更新缓存是一件很耗资源的事情。Opcache重建缓存时,不会禁止其他进程读取,所以会造成重复新建缓存。因此,要达到最好的性能分配:最好不要在高峰期清理缓存。高峰期不要频繁更新代码。清理缓存会导致重复创建缓存。如果需要更新缓存,可以尝试弱化服务器的权重,达到一个一个更新的目的。如果需要强制更新,可以尝试手动清空缓存重建Opcache缓存,尽量降低成本。