解决PHP Opcache 缓存刷新、代码重载出现无法更新代码的问题

 更新时间:2020年08月24日 10:05:48   作者:17ms  
这篇文章主要介绍了解决PHP Opcache 缓存刷新、代码重载出现的无法更新代码的问题,帮助大家更好的理解和学习php,感兴趣的朋友可以了解下

问题背景

通过启用Opcache的缓存优化,将PHP代码预编译为Opcode缓存到共享内存中供进程反复调用,从而减少了重复从磁盘解析PHP代码的时间消耗,显著的提高了PHP性能,提升了业务性能的调用,但是也引发了一些问题,就是我们每次更新了相应的PHP代码后,web server 无法即时加载到更新后的代码。

解决方案

(一)、设置Opcache脚本验证时间

可以通过更改 Opcache 以下两个配置选项来调整代码重载时间

opcache.revalidate_freq=0 检查脚本时间戳是否有更新的周期,以秒为单位。(如果设置为 0 会导致针对每个请求, OPcache 都会检查脚本更新)

opcache.validate_timestamps=0 如果启用,那么 OPcache 会每隔 opcache.revalidate_freq 设定的秒数 检查脚本是否更新。

PS:在实际生产环境中,为了尽可能达到最优性能,尽量不开启文件更新验证,因为每次验证都会重新预编译PHP代码到共享内存中。

(二)、重启 | 重载 php-fpm 进程

每次重启或重启 php-fpm 进程便会重新解析PHP脚本文件,但是重启 fpm 进程可能会导致请求中断,从而导致写入脏数据 或者 造成事务回滚等一系列异常。

重载相对于重启则平顺很多,不会导致用户请求直接中断,相对来说风险低很多,但是php-fpm 收到reload信号,便会向所有子进程发送SIGGUIT信号,同时注册一个定时器,在规定的时间之内子进程没有退出,接着在发送SIGTERM信号,结束子进程。如果在一秒之内子进程还是没结束 直接发送SIGKILL 强制杀死。

重启php-fpm

service php-fpm restart

重载php-fpm

services php-fpm reload

或 kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

(三)、手动清理缓存

除了上面的两种方式,还有更为稳妥一点的缓存清理,我们可以通过opcache_reset()和opcache_invalidate() 函数来刷新Opcache缓存。

opcache_reset() - 重置整个Opcode缓存,所有的PHP脚本将会被重新解析再预编译为Opcode。

opcache_invalidate() - 清除指定脚本缓存,可以传递两个参数,一个是刷新文件路径,一个是force字段, 如果 force 没有设置或者传入的是 FALSE,那么只有当脚本的修改时间 比对应Opcode的时间更新时,脚本的缓存才会失效。

需要注意的是,当PHP以PHP-FPM的方式运行的时候,opcache的缓存是无法通过php命令进行清除的,只能通过http或cgi到php-fpm进程的方式来清除缓存,我们可以编写一个对外接口,来达到清理缓存的目的。

相关实现如下(框架:laravel):

Route::any('cache-reset', function () {
  //重置整个Opcode缓存
  dd(opcache_reset());
});

Route::any('cache-update', function () {
  //清除掉最近一次更新文件的缓存
  exec('git diff --name-only HEAD~ HEAD', $output);
  foreach ($output as $file) {
    $path = base_path($file);
    opcache_invalidate($path, true);
  }
  dd('刷新完成');
});

总结

通过上面的三种策略,可以实现 Opcache 缓存更新的目的,但是在流量高峰期或者大流量的服务端,每次更新缓存都是一件非常损耗资源的事情,Opcache在重建缓存时,也不会禁止其他进程读取,因此就会造成反复新建缓存,因此想要达到最佳的性能调配:

  • 最好不要在高峰期清理缓存
  • 高峰期不要频繁的更新代码,清理缓存,会造成重复新建缓存
  • 如果需要更新,可以尝试削弱服务端权重,实现逐个更新的目的。
  • 如果需要强制更新,尽量选择手动清除缓存的方式,来重建Opcache缓存,使代价最小化。

以上就是解决PHP Opcache 缓存刷新、代码重载出现无法更新代码的问题的详细内容,更多关于PHP Opcache 缓存刷新、代码重载的资料请关注脚本之家其它相关文章!

相关文章

  • 如何在PHP环境中使用ProtoBuf数据格式

    如何在PHP环境中使用ProtoBuf数据格式

    这篇文章主要介绍了如何在PHP环境中使用ProtoBuf数据格式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 简要剖析PHP的Yii框架的组件化机制的基本知识

    简要剖析PHP的Yii框架的组件化机制的基本知识

    这篇文章主要介绍了PHP的Yii框架的组件化机制的基本知识,对应用程序CWebApplication组件进行了简要剖析,需要的朋友可以参考下
    2016-03-03
  • 攻克CakePHP(PHP中的Ruby On Rails框架)图文介绍

    攻克CakePHP(PHP中的Ruby On Rails框架)图文介绍

    CakePHP框架实例介绍分析。图文并茂
    2008-10-10
  • 浅谈定义一个PHP函数

    浅谈定义一个PHP函数

    在过去很长一段时间里,PHP都是开发web应用的不二之选。现在7.x版本又填补了许多高级特性和现代化应用的需求,并且提高了开发者的效率。这门语言正不断的发生改变,找出这些变化,并停止过去的写法,放弃你原来的习惯并自豪的使用这些新特性,让你的代码更易读易懂。
    2021-05-05
  • php中的数组操作函数整理

    php中的数组操作函数整理

    PHP 中的数组实际上是一个有序图。图是一种把 values 映射到 keys 的类型。此类型在很多方面做了优化,因此可以把它当成真正的数组来使用,或列表(矢量),散列表(是图的一种实现),字典,集合,栈,队列以及更多可能性。因为可以用另一个 PHP 数组作为值,也可以很容易地模拟树。
    2008-08-08
  • 详解PHP优化巨量关键词的匹配

    详解PHP优化巨量关键词的匹配

    本文完整介绍了我的实现方式,如何将需要运行十小时的任务优化到十分钟以内。虽然实现语言是PHP,但本文介绍的更多的思想,应该能给大家一些帮助。
    2021-05-05
  • php中如何使对象可以像数组一样进行foreach循环

    php中如何使对象可以像数组一样进行foreach循环

    php中如何使对象可以像数组一样进行foreach循环呢?下面小编就详细的为大家介绍一下吧!需要的朋友可以 过来参考下
    2013-08-08
  • PHP生成可点击刷新的验证码简单示例

    PHP生成可点击刷新的验证码简单示例

    这篇文章主要介绍了PHP生成可点击刷新的验证码,结合简单实例形式分析了php验证码的实现与调用显示方法,涉及js动态调用验证码php文件的相关技巧,需要的朋友可以参考下
    2016-05-05
  • PHP中register_shutdown_function函数的基础介绍与用法详解

    PHP中register_shutdown_function函数的基础介绍与用法详解

    php中的异常捕获没有java的强大,有些情况下,需要知道某段php程序业务是否正常执行完,可以用register_shutdown_function函数来辅助实现,这篇文章主要给大家介绍了关于PHP中register_shutdown_function函数的基础介绍与用法的相关资料,需要的朋友可以参考。
    2017-11-11
  • PHP array_push 数组函数

    PHP array_push 数组函数

    想到PHP操作数组时候,给一个数组添加一个数组单元时候可以有两种方式
    2009-12-12

最新评论