PHP7 opcache缓存清理问题

PHP7 opcache缓存清理问题

背景

OPcache通过opcode的缓存和优化,提供更快的PHP执行过程。
业务在php7环境运营时,为了提升请求的性能,在PHP7环境中配置OPcache扩展。
业务在更新代码后,访问业务系统时提示无法找到对应的文件或请求的内容还是更新前的旧内容,
webserver重启以后,请求访问到的文件就都是最新的了,问题就貌似解决了。

问题分析

根据现象分析,代码更新后请求找不到新增的文件,尤其是还在请求已有文件更新前的内容,那么可能跟缓存有关系,考虑到跟业务代码逻辑无关,关闭opcache的配置问题就不再出现,基本上可以定位到问题出在opcache的配置上。

cat /usr/local/php/etc/subconfig/opcache.inizend_extension=opcache.soopcache.enable=1opcache.revalidate_freq=0opcache.validate_timestamps=0opcache.max_accelerated_files=7963opcache.memory_consumption=192opcache.interned_strings_buffer=16opcache.fast_shutdown=1opcache.enable_cli=1

opcache.enable 启用操作码缓存,默认为“1”

如果禁用此选项,则不会优化和缓存代码。 在运行期使用 ini_set() 函数只能禁用 opcache.enable 设置,不可以启用此设置。 如果在脚本中尝试启用此设置项会产生警告。

opcache.enable_cli  仅针对 CLI 版本的 PHP 启用操作码缓存。

通常被用来测试和调试。

opcache.revalidate_freq=0  检查脚本时间戳是否有更新的周期,以秒为单位。

设置为 0 会导致针对每个请求, OPcache 都会检查脚本更新。

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

如果禁用此选项,你必须使用 opcache_reset() 或者 opcache_invalidate() 函数来手动重置 OPcache,也可以 通过重启 Web 服务器来使文件系统更改生效。

最初的配置是:
opcache.revalidate_freq=60,opcache.validate_timestamps=1
即每60秒检测一次更新字节码缓存,业务代码更新后可能需要60秒以后才能访问到最新的内容,也就出现了最初访问不到新增的内容。

代码更新方式

php代码的更新方式有两种,一种是覆盖webserver配置的目录下的文件来更新,一种是每次都部署一个全量包目录,然后软链接到webserver指定的目录。

第一种覆盖更新的方式,如果使用在过期时间后自动清理opcache缓存内容的话,更新操作如果有延迟,就会出现新旧代码文件混合在一起的情况。

第二种全量包目录发布后,软链接到webserver指定路径的方式,虽然不会存在新旧文件混合的问题,但是在未自动清理时,即便webserver已经链接到webserver对应目录,业务访问的还是旧文件。

代码缓存的问题

目前使用rsync同步目录文件的方式是我们更新代码的主要方式,最初使用每60s定时清理opcache的缓存文件,在60s内更新的文件不会生效,就导致了业务反馈代码更新后访问不到的问题。

使用定时更新代码缓存的问题,还有更新文件较多时,代码文件发布的过程中缓存发生更新,将会有60s新旧文件的缓存混合存在的问题。

根据相关研究人员推荐,如果采用覆盖更新代码文件时,更新操作完毕后,手动清理缓存比较合适。

opcache.validate_timestamps=0

即,将oopcache.validate_timestamps设置为0。

配置了opcache.validate_timestamps值为0,必须手动清空Zend OPcache缓存的字节码,才能访问到最新的文件内容。适合在生产环境中设置为0,但在开发环境会带来不便,可以在开发环境中这样配置启用自动验证缓存功能:

opcache.validate_timestamps=1
opcache.revalidate_freq=0

手动清理缓存

除了重启php-fpm的进程可以清理opcache缓存外,
手动清理缓存涉及到的opcache函数主要为:opcache_reset()和opcache_invalidate() 。

boolean opcache_reset ( void )
该函数将重置整个字节码缓存。 在调用 opcache_reset() 之后,所有的脚本将会重新载入并且在下次被点击的时候重新解析。

需要注意的是,当PHP以PHP-FPM的方式运行的时候,opcache的缓存是无法通过php命令进行清除的,只能通过http或cgi到php-fpm进程的方式来清除缓存。

In some (most?) systems,PHP‘s CLI has a separate opcode cache to the one used by the web server ,or PHP-FPM process,which means running opcache_reset() in the CLI,won‘t reset the webserver/fpm opcode cache, and vice-versa.

曲线救国,使用命令行清理php-fpm的opcache缓存:

#!/bin/bashcgi-fcgi -v  > /dev/null 2>&1|| yum --enablerepo=epel install fcgi -y  > /dev/null 2>&1echo ‘<?php opcache_reset(); echo "ok\n";‘ > /tmp/php-fpm-opcache-reset.php;
SCRIPT_FILENAME=/tmp/php-fpm-opcache-reset.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000;
rm -f /tmp/php-fpm-opcache-reset.php;

opcache_invalidate  废除指定脚本缓存

boolean opcache_invalidate ( string $script [, boolean $force = FALSE ] )
该函数的作用是使得指定脚本的字节码缓存失效。 如果 force 没有设置或者传入的是 FALSE,那么只有当脚本的修改时间 比对应字节码的时间更新,脚本的缓存才会失效。

参数 

script
缓存需要被作废对应的脚本路径

force
如果该参数设置为TRUE,那么不管是否必要,该脚本的缓存都将被废除。

opcache_invalidate可以针对单个或几个脚本进行来清理缓存。

总结

如果代码发布是全量发布,切换软链接的方式,可以设置opcache.validate_timestamps=1和opcache.validate_timestamps=1来定时自动更新缓存。

如果代码发布是覆盖更新旧目录,则可以重启php-fpm及在脚本中或代码文件中使用opcache_reset函数来清理所有缓存。

如果可以获取到更新的代码文件列表,则可以使用opcache_invalidate函数来清理代码,同时也可以避免影响到其他业务的缓存。

时间: 2024-12-28 14:47:17

PHP7 opcache缓存清理问题的相关文章

手机卫士11_ 自定义控件_缓存清理_病毒库更新

拷贝安卓源码中的逻辑,可以考虑先创建一个小项目实现以下效果 1,病毒数据库的自动更新(连接网络,然后获取特征码保存到数据库?) ①工程师发现病毒apk,获取到它的特征码发布到服务器上 通过 MD5 或者ASH1获取特征码 ②客户端杀毒软件下载特征码(可能是 JSON串)到本地客户端 (在打开软件的时候还是打开查杀界面的时候?其实都不适合,应该开启一个服务去定期更新数据库,访问病毒更新特征码地址) 定期更新,timer和timertask,一般一个小时更新一次(测试的时候写短一点) 连接服务器:U

搭建LNMP发布ecshop系统及压测启用opcache缓存与否的情况

安装环境:CENTOS6.5,nginx1.6.2,php-5.5.18,mysql5.5.38 在安装软件之前安装epel源,就可以直接用yum安装libmcrypt,mhash,mcrypt等php扩展. 安装nginx 解决依赖关系,安装开发包组"Development Tools"和 "Server Platform Development". #tar –xf nginx-1.6.2 ./configure \ --prefix=/usr/local/ng

手机安全卫士——缓存清理

CleanCacheActivity.java /** * 缓存清理*/ public class CleanCacheActivity extends Activity { private PackageManager packageManager; private List<CacheInfo> cacheLists; private ListView list_view; @Override protected void onCreate(Bundle savedInstanceStat

Android Glide数据更新及内存缓存、硬盘缓存清理

[转] 原文                                         Android Glide数据更新及内存缓存.硬盘缓存清理 Android的Glide在加载图片时候内部默认使用了缓存机制,Glide的缓存机制分为两级,第一级是内存缓存,然后第二级是硬盘缓存.缓存的过程首先是在内存中缓存,然后将加载的图片资源缓存到硬盘,这样就可以在随后的再次加载中使用缓存了,Glide使用缓存时候首先要检查内存这一层级是否缓存了相应的缓存,如果有,则直接使用,如果没有,则深入到硬盘缓

Hibernate中的脏检查和缓存清理机制

脏检查 Session到底是如何进行脏检查的呢?当一个Customer对象被加入到Session缓存中时,Session会为Customer对象的值类型的属性复制一份快照.当Session清理缓存时,会先进行脏检查,即比较Customer对象的当前属性与它的快照,来判断Customer对象的属性是否发生了变化,如果发生了变化,就称这个对象是“脏对象”,Session会根据脏对象的最新属性来执行相关的SQL语句,从而同步更新数据库. 脏数据检查: 什么是脏数据?脏数据并不是废弃和无用的数据,而是状

php的opcache缓存扩展

opcache (全程 zend opcache): 从php5.5开始,默认提供的php脚本缓存扩展,编译php5.5时加上参数--enable-opcache就可以编译opcache了,只是要启用的话必须配置. 原理: 其实非常简单,opcache只是把把PHP执行后的数据(opcode)缓存到内存中从而避免重复的编译过程,能够直接使用缓冲区已编译的opcode代码从而提高速度,降低服务器负载 效果: 在实际应用当中能使QPS数大致增加3倍以上 注意事项: 启用opcache后,典型的问题就

脏检查 和 缓存清理机制

Session到底是如何进行脏检查的呢?当一个Customer对象被加入到Session缓存中时,Session会为Customer对象的值类型的属性复制一份快照.当Session清理缓存时,会先进行脏检查,即比较Customer对象的当前属性与它的快照,来判断Customer对象的属性是否发生了变化,如果发生了变化,就称这个对象是“脏对象”,Session会根据脏对象的最新属性来执行相关的SQL语句,从而同步更新数据库. 缓存清理机制 当Session缓存中对象的属性每次发生了变化,Sessi

Hibernate——脏检查和缓存清理机制

脏检查 Session到底是如何进行脏检查的呢?当一个Customer对象被加入到Session缓存中时,Session会为Customer对象的值类型的属性复制一份快照.当Session清理缓存时,会先进行脏检查,即比较Customer对象的当前属性与它的快照,来判断Customer对象的属性是否发生了变化,如果发生了变化,就称这个对象是“脏对象”,Session会根据脏对象的最新属性来执行相关的SQL语句,从而同步更新数据库. 缓存清理机制 当Session缓存中对象的属性每次发生了变化,S

关于IE缓存清理——尤其对Web前台开发人员

当我们开发过程中修改了JS等文件之后,发现IE使用的还是原先的文件.这是因为一般情况下,IE会将JS.CSS文件.图片文件进行缓存,下次读取的时候首先从缓存读取,如果没有才获取新的文件.因此,在开发过程中如果这些文件修改过,应该及时清理IE缓存,否则效果无法呈现. 一般清理IE缓存的方法:(我目前是英文版Win7,IE10,中文版类似) IE-->Tools-->Internet Options-->点击Delete按钮. 在弹出的界面中按Delete按钮 上述方法想必大家都知道. 重点