关于PHP缓存扩展APCu缓存莫名其妙被清空和APCu缓存有效期的说明

三郎 10天前 15

PHP有几个常用的缓存扩展,包括APCuredismemcachedwincache

其中redismemcached用tcp连接,有连接开销

APCuwincache没有连接开销

wincache只能用于Windows系统,如果已经缓存key比较少的话,wincache_ucache_set缓存速度还是比较快的,比redis快好几倍,如果已经缓存了很多key,那wincache_ucache_set速度就比较慢了,比redis还慢几倍都可能,不过wincache_ucache_get读取速度不管什么情况下都是比redis快的,而且这个缓存是所有进程共享的,所以Windows系统还是比较推荐wincache扩展的。


今天的主角是APCu,很多网络文章中都有对这个php扩展的使用说明和测试,都说APCu很快,比redis快10倍甚至更多,我也试过APCu确实快。但是有一个问题一直有困扰,导致不敢去用APCu。

原因是在php中用apcu_store添加缓存后,添加的key有时候会莫名其妙消失,也就是好像APCu缓存会自己被清空,查找了网上很多文章都没有找到原因。在官网上也没有具体的说明,官方GitHub也没有具体说明,倒是有个碰到登录后莫名奇妙会自动退出的发了提问。官方只有一条说明就是APCu缓存与进程相关。

今天做了测试,得出的结论是:APCu缓存有效期确实与php进程有关,具体的说就是APCu缓存与用apcu_store提交了缓存的php进程的(PID)生命周期直接挂钩,只要这个PID的php进程没有意外停止或者没有过期被杀掉,那么通过apcu_store提交的缓存就一直有效,当这个进程结束时,所有通过这个进程提交的APCu缓存也会随之被清空。

当前很多web server软件都是通过fastcig等多进程方式运行php的,例如IIS、apache、kangle等,在配置服务器的时候都会为php配置有效生命周期,例如php空闲时间。当第一个访客访问网站时,服务器会开启一个php进程,假如这个php进程提交了一条APCu缓存,访问结束后,这个php进程不会立马被关闭,而是根据设置的空闲时间在进程池中等待,假设设置了空闲时间为60秒,当60秒内来了另外一个访客,不管他访问的是哪个网址,只要是同一个网站,服务器就会查看这个网站的进程池中有没有空闲的php进程,这时候发现刚才开启的那个php进程还在,就把这个进程分配给了这个新访客,因为这个访客和前面的那个访客用的是同一个php进程,所以能正常读取到前面提交的APCu缓存。如果60秒内没有其他访客来访,服务器就把超过设置时间的php进程杀掉了,同时前面提交的APCu缓存也被清空,之后如果有新访客,服务器会新开一个php进程,这时就读取不到APCu缓存了。

所以如果网站的访问量不大的话,要使用APCu缓存,就需要在web server中把php进程空闲时间设置长一点(注意:这里设置的不是php.ini配置文件里面的php最大允许运行时间),比如60秒、120秒等,否则新访客是读取不到APCu缓存的,或者干脆不用APCu缓存,因为确实没必要。


还有另外一种情况,就是网站在同一时间内的访问量比较大,当第一个访客来访时,php还没有处理完数据,这时又来了一个访客,服务器会新开一个php进程,因为两个php进程是不同的,所以这个新访客也是获取不到第一个访客提交的APCu缓存的,只能再提交一份给下一个被分配了同一个PID的php进程的访客使用。所以这时可能会有很多份APCu缓存同时存在。


当然,如果在web server软件中设置了不允许php进程空闲,比如设置进程空闲时间为0秒,服务器就会为每一个新访客开启一个新的php进程,这时APCu缓存只能让一个访客使用,这个访客的这次访问结束后,他提交的APCu缓存就随之清空了,其他访客是不能共享的。


所以,这就出现了APCu缓存会莫名其妙消失的情况,实际上是php进程因为等待太久也没有新访客来使用它而被系统杀掉了。


这里还有一点需要说明的,如果在web server软件中为不同的网站设置了共享进程池,那么理论上不同的网站访客间是可以获取到同样的APCu缓存的,所以这种情况下,最好每个网站的缓存设置不同key前缀。

最新回复 (0)
返回
发新帖