PHP APC缓存配置、使用详解


Posted in PHP onMarch 06, 2014

一、APC缓存简介
APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”。它为我们提供了缓存和优化PHP的中间代码的框架。 APC的缓存分两部分:系统缓存和用户数据缓存。
系统缓存
它是指APC把PHP文件源码的编译结果缓存起来,然后在每次调用时先对比时间标记。如果未过期,则使用缓存的中间代码运行。默认缓存
 3600s(一小时)。但是这样仍会浪费大量CPU时间。因此可以在php.ini中设置system缓存为永不过期(apc.ttl=0)。不过如果这样设置,改运php代码后需要重启WEB服务器。目前使用较多的是指此类缓存。
用户数据缓存
缓存由用户在编写PHP代码时用apc_store和apc_fetch函数操作读取、写入的。如果数据量不大的话,可以一试。如果数据量大,使用类似memcache此类的更加专著的内存缓存方案会更好
缓存key生成规则
APC的缓存中的每个slot都会有一个key,key是
 apc_cache_key_t结构体类型,除了key相关的属性,关键是h字段的生成。 h字段决定了此元素落于slots数组的哪一个位置。对于用户缓存和系统缓存,其生成规则不同。 用户缓存通过apc_cache_make_user_key函数生成key。通过用户传递进来的key字符串,依赖PHP内核中的hash函数(PHP的hashtable所使用的hash函数:zend_inline_hash_func),生成h值。
系统缓存通过apc_cache_make_file_key函数生成key。通过APC的配置项apc.stat的开关来区别对待不同的方案。在打开的情况下,即
 apc.stat= On 时,如果被更新则自动重新编译和缓存编译后的内容。此时的h值是文件的device和inode相加所得的值。在关闭的情况下,即apc.stat=off时,当文件被修改后,如果要使更新的内容生效,则必须重启Web服务器。此时h值是根据文件的路径地址生成,并且这里的路径是绝对路径。即使你是使用的相对路径,也会查找PG(include_path)定位文件,以取得绝对路径,所以使用绝对路径会跳过检查,可以提高代码的效率。
添加缓存过程
以用户缓存为例,apc_add函数用于给APC缓存中添加内容。如果key参数为字符串中,APC会根据此字符串生成key,如果key参数为数组,APC会遍历整个数组,生成key。根据这些key,APC会调用_apc_store将值存储到缓存中。由于这是用户缓存,当前使用的缓存为apc_user_cache。执行写入操作的是apc_cache_make_user_entry函数,其最终调用apc_cache_user_insert执行遍历查询和写入操作。与此对应,系统缓存使用apc_cache_insert执行写入操作,其最终都会调用_apc_cache_insert。
不管是用户缓存还是系统缓存,大体的执行过程类似,步骤如下:

通过求余操作,定位当前key的在slots数组中的位置: cache->slots[key.h % cache->num_slots];
在定位到slots数组中的位置后,遍历当前key对应的slot链表,如果存在slot的key和要写入的key匹配或slot过期,清除当前slot。
在最后一个slot的后面插入新的slot。
二、APC模块安装

A.WINDOWS下安装APC
第一步:下载php_apc.dll 在http://pecl.php.net/package/apc 要与php版本对应 将php_apc.dll放入你的ext目录
第二步:让php.ini支持apc扩展模块。 然后打开php.ini 加入:

extension=php_apc.dll
apc.rfc1867 = on
apc.max_file_size = 100M
upload_max_filesize = 100M
post_max_size = 100M
//以上参数可自己定义

第三步:检查是否支持PHP APC apc_store apc_fetch
查看phpinfo中是否有apc相关项

B.LIUNX下安装APC
第一步:下载和安装
wget http://pecl.php.net/get/APC-3.1.8.tgz
tar -zxvf APC-3.1.8.tgz cd APC-3.1.8
/usr/local/php/bin/phpize
./configure --enable-apc --enable-mmap --enable-apc-spinlocks --disable-apc-pthreadmutex --with-php-config=/usr/local/php/bin/php-config
make
sudo make install
第二步:配置APC
在/usr/local/php/etc/php.ini 加入以下配置项:

extension = "apc.so" ;
;APC setting
apc.enabled = 1
apc.shm_segments = 1
apc.shm_size = 64M
apc.optimization = 1
apc.num_files_hint = 0
apc.ttl = 0
apc.gc_ttl = 3600
apc.cache_by_default = on

第三步:检查安装是否成功
重启apache 或者 /usr/local/php/sbin/php-fpm restart
查看phpinfo中是否有apc相关项
三、配置参数详解和使用总结
1).APC模块的参数配置详解
apc.enabled  布尔型 
apc.enabled 可以被设成 0 来禁用 APC。这主要是有用的,当 APC 被静态编译入 PHP 时,因为没有其它方法来禁用它(当编译为 DSO 的时候,可以将 php.ini 中的 extension 行注释掉)。apc.shm_segments  整型 
对编译缓存分配共享内存块的数量。如果APC用光了共享内存,而且你已经设置apc.shm_size为系统允许的最大值的情况下,你可以试着去提高这个参数的值。
apc.shm_size  整型 
每个共享内存块的大小是以MB为单位的。在默认情况下,一些系统(包括大多数BSD变种系统)的共享内存块的大小限制的很低。
apc.optimization  整型
优化等级。设为0则禁用优化,越高的值使用越强有力的优化。期待有适度的速度上的改进。这个还是实验性质的。
apc.num_files_hint  整型
对在你的Web服务器上被包含和请求的不同的源文件的数量的提示。如果你无法确定,设置为0或者省略;这个设置主要可能用于有成千的源文件的站点。
apc.ttl  整型
当一个缓存条目在缓存区的位置被另一个条目需要时,我们需要考虑的是这个缓存条目在缓存区的位置被允许空闲的秒数。将这个参数设置为0意味着你的缓存可能充满不新鲜的条目,同时导致新的条目无法被缓存。
apc.gc_ttl  整型
缓存条目在垃圾收集列表中存活的秒数。这个值提供了出错保护在执行一个缓存源文件,而同时服务器进程死了的事件中。如果那个源文件被修改,内存分配给旧版本的缓存条目将不会被回收,直到这个参数设定的TTL值到的时候。设置为0就是禁止这个特性。
apc.cache_by_default  布尔型
默认为On,但可以被设置为Off并和以加号开头的apc.filters配合使用,文件仅仅在匹配过滤器时才被缓存。
apc.filters  字符串
一个以逗号分割的POSIX扩展正则表达式的列表。如果任何模式匹配源文件名,这个文件将不会被缓存。注意用来匹配的文件名是传递给 include/require 的文件名,而不是绝对路径。如果正则表达式的第一个字符是 + ,则这个表达式就意味着任何匹配表达式的文件将会被缓存,如果第一个字符是 - 则任何匹配都不会被缓存。 - 是默认值,所以可以被省略。
apc.mmap_file_mask  字符串 (这段实在不太懂,所以没有翻译)
If compiled with MMAP support by using --enable-mmap this is the mktemp-style file_mask to pass to the mmap module for determing whether your mmap'ed memory region is going to be file-backed or shared memory backed. For straight file-backed mmap, set it to something like/tmp/apc.XXXXXX (exactly 6 Xs). To use POSIX-style shm_open/mmap put a .shm somewhere in your mask. e.g. /apc.shm.XXXXXX You can also set it to /dev/zero to use your kernel's/dev/zero interface to anonymous mmap'ed memory. Leaving it undefined will force an anonymous mmap. 
apc.slam_defense  整型
在非常繁忙的服务器上,无论你启动服务还是修改文件,你都会导致一种多进程都试图在同一个时间缓存同一个文件的竞争。这个选项设置了进程跳过试图去缓存一个未被缓存的文件的百分比。或者可以把这个想象成一个单独进程跳过缓存的机率。例如,设置apc.slam_defense为75就意味着进程有75%的机率不去缓存未被缓存的文件。所以,设置的越高,越能减少缓存的碰撞机率。设置为0则禁用这个特性。
apc.file_update_protection  整型
当你在一个运行着的服务器上修改文件时,你应该执行原子操作。也就是,先写一个临时文件,当写完后再重命名(mv)这个文件到它的最终位置。许多文本编辑器,cp,tar和其他一些类似程序都不是这样操作的。这就意味着有机会去访问和(缓存)文件,当这个文件还在被写的情况下。apc.file_update_protection的设置使得缓存标记新文件的延迟。默认值是2,意味着如果发现文件的修改时间距离访问时间不到2秒,文件将不会被缓存。访问写到一半的文件的不幸用户将会看到离奇的情况,但至少这种情况不是持续的。如果你确信你经常使用原子操作来更新你的文件,你可以关闭这个保护通过设置这个参数为0。如果你的系统充满io操作,并导致更新程序花费超过2秒,你可能需要去增大这个值。
apc.enable-cli  整型
大多是为了测试和调试。为CLI版本的PHP开启动APC功能。一般来说,你将不会想到为每一个CLI请求创建,移植和放弃APC的缓存,但对于各种测试情况,这是很容易的为了CLI版本开启APC。

2).使用总结
1,使用Spinlocks锁机制,能够达到最佳性能。
2,APC提供了apc.php,用于监控与管理APC缓存。不要忘记修改管理员名和密码
3,APC默认通过mmap匿名映射创建共享内存,缓存对象都存放在这块”大型”的内存空间。由APC自行管理该共享内存
4,我们需要通过统计调整apc.shm_size、apc.num_files_hints、apc.user_entries_hint的值。直到最佳
5,好吧,我承认apc.stat = 0 可以获得更佳的性能。要我做什么都可以接受.
6,PHP预定义常量,可以使用apc_define_constants()函数。不过据APC开发者介绍说pecl hidef性能更佳,抛异define吧,它是低效的。
7,函数apc_store(),对于系统设置等PHP变量,生命周期是整个应用(从httpd守护进程直到httpd守护进程关闭),使用APC比Memcached会更好。必竟不要经过网络传输协议tcp。
8,APC不适于通过函数apc_store()缓存频繁变更的用户数据,会出现一些奇异现象。

四、使用实例
下面引用initphp框架的APC缓存类

<?php 
if 
class Apc{     /**
     * Apc缓存-设置缓存
     * 设置缓存key,value和缓存时间
     * @param  string $key   KEY值
     * @param  string $value 值
     * @param  string $time  缓存时间
     */ 
    public function set_cache($key, $value, $time = 0) {  
        if ($time == 0) $time = null; //null情况下永久缓存 
        return apc_store($key, $value, $time);; 
    } 
     
    /**
     * Apc缓存-获取缓存
     * 通过KEY获取缓存数据
     * @param  string $key   KEY值
     */ 
    public function get_cache($key) { 
        return apc_fetch($key); 
    } 
    /**
     * Apc缓存-清除一个缓存
     * 从memcache中删除一条缓存
     * @param  string $key   KEY值
     */ 
    public function clear($key) { 
        return apc_delete($key); 
    } 
    /**
     * Apc缓存-清空所有缓存
     * 不建议使用该功能
     * @return
     */ 
    public function clear_all() { 
        apc_clear_cache('user'); //清除用户缓存 
        return apc_clear_cache(); //清楚缓存 
    } 
    /**
     * 检查APC缓存是否存在
     * @param  string $key   KEY值
     */ 
    public function exists($key) { 
        return apc_exists($key); 
    } 
    /**
     * 字段自增-用于记数
     * @param string $key  KEY值
     * @param int    $step 新增的step值
     */ 
    public function inc($key, $step) { 
        return apc_inc($key, (int) $step); 
    } 
    /**
     * 字段自减-用于记数
     * @param string $key  KEY值
     * @param int    $step 新增的step值
     */ 
    public function dec($key, $step) { 
        return apc_dec($key, (int) $step); 
    } 
    /**
     * 返回APC缓存信息
     */ 
    public function info() { 
        return apc_cache_info(); 
    } 
}
PHP 相关文章推荐
用IE远程创建Mysql数据库的简易程序
Oct 09 PHP
PHP chmod 函数与批量修改文件目录权限
May 10 PHP
php学习之简单计算器实现代码
Jun 09 PHP
php入门学习知识点一 PHP与MYSql连接与查询
Jul 14 PHP
详解WordPress中添加和执行动作的函数使用方法
Dec 29 PHP
PHP目录与文件操作技巧总结(创建,删除,遍历,读写,修改等)
Sep 11 PHP
Zend Framework实现自定义过滤器的方法
Dec 09 PHP
php 解决扫描二维码下载跳转问题
Jan 13 PHP
thinkPHP实现的省市区三级联动功能示例
May 05 PHP
thinkPHP通用控制器实现方法示例
Nov 23 PHP
php 利用socket发送GET,POST请求的实例代码
Jul 04 PHP
基于php伪静态的实现方法解析
Jul 31 PHP
PHP程序漏洞产生的原因分析与防范方法说明
Mar 06 #PHP
PHP常用函数和常见疑难问题解答
Mar 05 #PHP
php获得url参数中具有&amp;的值的方法
Mar 05 #PHP
php网页标题中文乱码的有效解决方法
Mar 05 #PHP
php绘图中显示不出图片的原因及解决
Mar 05 #PHP
ThinkPHP验证码使用简明教程
Mar 05 #PHP
ThinkPHP分页类使用详解
Mar 05 #PHP
You might like
php学习笔记 面向对象的构造与析构方法
2011/06/13 PHP
浅析PKI加密解密 OpenSSL
2013/07/01 PHP
php实现的mongodb操作类实例
2015/04/03 PHP
基于laravel-admin 后台 列表标签背景的使用方法
2019/10/03 PHP
用JQuery 实现的自定义对话框
2007/03/24 Javascript
JQuery触发radio或checkbox的change事件
2012/12/18 Javascript
JS制作简单的三级联动
2015/03/18 Javascript
JavaScript的History API使搜索引擎抓取AJAX内容
2015/12/07 Javascript
ES6新特征数字、数组、字符串
2016/10/01 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
node.js实现回调的方法示例
2017/03/01 Javascript
Angular-UI Bootstrap组件实现警报功能
2018/07/16 Javascript
Vue.js实现的购物车功能详解
2019/01/27 Javascript
JS精确判断数据类型代码实例
2019/12/18 Javascript
js实现盒子移动动画效果
2020/08/09 Javascript
深入讲解Python函数中参数的使用及默认参数的陷阱
2016/03/13 Python
Python对文件操作知识汇总
2016/05/15 Python
python爬虫框架talonspider简单介绍
2017/06/09 Python
Django model.py表单设置默认值允许为空的操作
2020/05/19 Python
Python加速程序运行的方法
2020/07/29 Python
Python爬取微信小程序Charles实现过程图解
2020/09/29 Python
Python实现扫码工具的示例代码
2020/10/09 Python
Dower & Hall官网:英国小众轻奢珠宝品牌
2019/01/31 全球购物
潘多拉珠宝美国官方网站:Pandora US
2020/06/18 全球购物
如果有两个类A,B,怎么样才能使A在发生一个事件的时候通知B
2016/03/12 面试题
J2EE系统只能是基于web
2015/09/08 面试题
个人自我评价范文
2014/02/05 职场文书
2014两会优秀的心得体会范文
2014/03/17 职场文书
新兵入伍心得体会
2014/09/04 职场文书
四风问题个人自查剖析材料思想汇报
2014/09/21 职场文书
分居协议书范本(律师见证版)
2014/11/26 职场文书
2015年七七事变78周年纪念活动方案
2015/05/06 职场文书
关于环保的广播稿
2015/12/17 职场文书
goland设置颜色和字体的操作
2021/05/05 Golang
OpenCV 图像梯度的实现方法
2021/07/25 Python
vue3获取当前路由地址
2022/02/18 Vue.js