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


Posted in PHP onAugust 24, 2020

问题背景

通过启用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 相关文章推荐
在PWS上安装PHP4.0正式版
Oct 09 PHP
php db类库进行数据库操作
Mar 19 PHP
支持中文的php加密解密类代码
Nov 27 PHP
php使用smtp发送支持附件的邮件示例
Apr 13 PHP
PHP实现定时执行任务的方法
Oct 05 PHP
php中ob_flush函数和flush函数用法分析
Mar 18 PHP
深入探究PHP的多进程编程方法
Aug 18 PHP
PHP curl模拟登录带验证码的网站
Nov 30 PHP
Thinkphp3.2.3分页使用实例解析
Jul 28 PHP
浅谈mysql_query()函数的返回值问题
Sep 05 PHP
php 删除指定文件夹的实例讲解
Jul 25 PHP
php实现简单四则运算器
Nov 29 PHP
WordPress免插件实现面包屑导航的示例代码
Aug 20 #PHP
VSCode+PHPstudy配置PHP开发环境的步骤详解
Aug 20 #PHP
Laravel相关的一些故障解决
Aug 19 #PHP
聊聊 PHP 8 新特性 Attributes
Aug 19 #PHP
php提高脚本性能的4个技巧
Aug 18 #PHP
php判断IP地址是否在多个IP段内
Aug 18 #PHP
PHP 8新特性简介
Aug 18 #PHP
You might like
解析php开发中的中文编码问题
2013/08/08 PHP
php多用户读写文件冲突的解决办法
2013/11/06 PHP
jQuery EasyUI API 中文文档 - Draggable 可拖拽
2011/09/29 Javascript
ASP.NET中AJAX 调用实例代码
2012/05/03 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
2014/06/23 Javascript
在JavaScript中使用对数Math.log()方法的教程
2015/06/15 Javascript
JavaScript实现的多种鼠标拖放效果
2015/11/03 Javascript
Bootstrap创建可折叠的组件
2016/02/23 Javascript
AngularJS教程之简单应用程序示例
2016/08/16 Javascript
js调用父框架函数与弹窗调用父页面函数的简单方法
2016/11/01 Javascript
javascript创建对象的3种方法
2016/11/02 Javascript
js数字舍入误差以及解决方法(必看篇)
2017/02/28 Javascript
Vue手把手教你撸一个 beforeEnter 钩子函数
2018/04/24 Javascript
nodejs 简单实现动态html的方法
2018/05/12 NodeJs
vue使用ElementUI时导航栏默认展开功能的实现
2018/07/04 Javascript
详解如何构建Promise队列实现异步函数顺序执行
2018/10/23 Javascript
JS复杂判断的更优雅写法代码详解
2018/11/07 Javascript
微信小程序访问豆瓣电影api的实现方法
2019/03/31 Javascript
详解JavaScript之ES5的继承
2020/07/08 Javascript
解决vue cli4升级sass-loader(v8)后报错问题
2020/07/30 Javascript
[01:30:54]《加油DOTA》 第三期
2014/08/18 DOTA
Python中字典(dict)和列表(list)的排序方法实例
2014/06/16 Python
Python脚本获取操作系统版本信息
2016/12/17 Python
Python实现简单生成验证码功能【基于random模块】
2018/02/10 Python
详解python异步编程之asyncio(百万并发)
2018/07/07 Python
pytorch方法测试——激活函数(ReLU)详解
2020/01/15 Python
python3中for循环踩过的坑记录
2020/12/14 Python
查找适用于matplotlib的中文字体名称与实际文件名对应关系的方法
2021/01/05 Python
测绘工程个人的自我评价
2013/11/23 职场文书
校园自助餐厅的创业计划书
2013/12/26 职场文书
心理健康心得体会
2014/01/02 职场文书
学生安全责任书范本
2014/07/24 职场文书
汽车4S店前台接待岗位职责
2015/04/03 职场文书
2015年销售内勤工作总结
2015/04/27 职场文书
javascript对象3个属性特征
2021/11/17 Javascript
python 镜像环境搭建总结
2022/09/23 Python