博客地址: http://blog.csdn.net/lgg201/archive/2010/09/11/5877798.aspx由于是在项目基础上测试, 不方便贴出测试代码, 见谅.
如果对测试结果不认同, 请提供测试方法及数据, 互相学习./**
 * @author: selfimpr
 * @blog: http://blog.csdn.net/lgg201
 * @mail: [email protected]
 */系统现有APC存储数据量: 70万条左右.测试数据: key, value都是15字节左右的随机字符串测试方法:
1. 测试每次运行10组, 每组10000次读/写, 使用jpgraph生成折线图.
2. 读/写分别测试, 不会互相影响.使用接口:
//Memcache接口  
$mem = new Memcache();  
$mem->connect('localhost', 11211);  
$mem->get();  
$mem->set();  
//Apc接口  
apc_store();  
apc_fetch();  
结论:
1. 在nginx+fastcgi的web环境下, apc随着数据量增大, 性能下降明显, 在超过8万条后, 性能低于Memcache
2. 在CLI模式下运行, apc性能稳定, 60万条数据一直远超memcache详细测试过程输出, 请参见博客.

解决方案 »

  1.   


    具体应用?
    http://php.net/manual/en/book.memcache.php
    http://php.net/manual/en/book.apc.php
    这些文档非常浅显易懂的缓存的使用, 本身就是简单的, 因为缓存的目的简单(以Memcache类缓存为例): 把一部分常用数据, 存储在内存中, 以降低硬盘的IO消耗.我觉得复杂的是以下几方面:
    1. 对哪些数据使用缓存
    2. 缓存数据时采用什么样的结构
    3. 对缓存周期的控制而几点, 一方面我自己也不是很能摸得着头脑啊, 另一方面这又多得结合实际的应用情况.
      

  2.   

    不错,有理有据的个人觉得memcache诱人的地方在于集群,易扩展
      

  3.   

    http://blog.joycode.com/ghj/archive/2007/09/01/107863.aspx
    看的文章缓存的过期策略  CSDN新版积分制论坛中,帖子列表缓存会在列表数据缓存达到600时,把它清理到550条数据。
      又比如新积分制论坛帖子的缓存过期,则是没有任何列表引用这个帖子后,则这个帖子过期。缓存的同步问题  解决方法很简单,把你的业务逻辑,代码触发情况都考虑清楚,不要遗留没有触底的地方。
      简单的方法会导致你的代码逻辑变得非常复杂。
      这也就是有些人,在非必要的时候,建议你不要用缓存的原因。一旦开始使用缓存,你就应该准备增加大量的代码来处理数据同步的问题。
      

  4.   


    //写入测试的相关代码
    while($j ++ < $times) { //$times表示组
    $memcache_time = 0; //memcache耗时累计
    $apc_time = 0; //apc耗时累计
    $i = 0;
    while($i ++ < $num_per_time) { //每组写入次数
    $key = uniqid('test_key'); //生成key
    $value = uniqid('test_value'); //生成value
    $start = microtime(true); //开始时间
                    //SharedMemory::create创建的是memcache连接, 这是我们封装的, 封装的东西绝对会比原生的Memcache慢, 所以, 对目前测试结果不产生影响
    $memcache = SharedMemory::create(DbConf::$JHX_REMOTE['engin'],DbConf::$JHX_REMOTE['options']);
    $memcache->set($key, $value); //设置值
    $end = microtime(true);
    $memcache_time += $end - $start; //累计Memcache写入耗时, 包括连接耗时
    $start = microtime(true);
    apc_store($key, $value); //apc写入
    $end = microtime(true);
    $apc_time += $end - $start; //累计apc写入耗时
    }
    $memcache_times[] = $memcache_time; //将两个时间分别记录到数组.
    $apc_times[] = $apc_time;
    }
    //最终是用$memcache_times和$apc_times这两个数组使用jpgraph生成图.
      

  5.   

    reply to #9觉得这样测试好像对memcache有点不公平, 不是吗?
      

  6.   

    lgg201, 这样再测试一次, 把结果帖图出来看看
    $memcache = SharedMemory::create(DbConf::$JHX_REMOTE['engin'],DbConf::$JHX_REMOTE['options']);
    while($j ++ < $times) { //$times表示组
        $memcache_time = 0; //memcache耗时累计
        $apc_time = 0; //apc耗时累计
        $i = 0;
        while($i ++ < $num_per_time) { //每组写入次数
            $key = uniqid('test_key'); //生成key
            $value = uniqid('test_value'); //生成value
            $start = microtime(true); //开始时间        $memcache->set($key, $value); //设置值
            $end = microtime(true);
            $memcache_time += $end - $start; //累计Memcache写入耗时, 包括连接耗时
            $start = microtime(true);
            apc_store($key, $value); //apc写入
            $end = microtime(true);
            $apc_time += $end - $start; //累计apc写入耗时
        }
        $memcache_times[] = $memcache_time; //将两个时间分别记录到数组.
        $apc_times[] = $apc_time;
    }
      

  7.   


    呵呵, 结果已经是Memcache在超过8万后比apc快了.
    而且, memcache的连接耗时是不能忽略的, 因为我们现在系统内的php不可能每几十万数据才创建一次连接(一次连接只为一个用户服务), 所以这个时间要考虑进去
      

  8.   


    不知你封装memcache的类是怎么写, 但如果要缓存的数据量大, 变化频繁, 应该用长连接再加个守护进程, 
    如果按php默认的做法, 每次都连接, 那消耗的资源太大了.我对你做的项目感兴趣, 如果不方便分开的话, 在技术和设计上, 可以写私信交流.
      

  9.   

    其实你说的jsp和jvm的关系好比, php和php扩展+memcache+服务器 的关系, 只不过php方面的应用结合比较松散, 要自己来组织.
      

  10.   

    你可以用c写一个连接池, 专门处理数据库和memcache之间的关系, 什么时间读缓存,什么时候读数据库,什么时候断掉数据库, 什么时候重新连接, 缓存多少时间更新一次, 资源怎么分配等.这些功能都由这个封装了的程序去处理, 你只传几个传数去调用就可以了, 假设数据交互太频繁, 这绝对要比你每次调用php去连接一次数据库, 或初始化一个memcache要好得多
      

  11.   


    用C写一个常驻进程来作为memcache连接池吗?
    那php与这个进程的通信以什么方式进行? 这个通信的耗时应该也需要计算的吧.ps: 这方面不太现实, 我们没有用c实现这些功能的人和时间, 呵呵, 谢谢.
      

  12.   

    那php与这个进程的通信以什么方式进行? 这个通信的耗时应该也需要计算的吧.
    --------------------关键还得看你这个进程怎么写, 至少这个通迅不用频繁连接数据库或多个程序, 这样节省时间.php本身设计是以最省资源方式去做, 所以被人称高负载, 但当它超过某一个值, 像你用mem和apc测试那样, 超过了那个临界点就有必要利用其它方法来解决,
      

  13.   


    我还使不太明白你的意思阿...不管这个进程写的多么精彩, 我们减少了php连接数据库服务进程, 连接memcache服务进程的次数, 但是却增加了php连接这个进程的消耗啊....
      

  14.   

    启动了几个php-cgi 进程和 nginx 进程。。呃 这是数据库负载吧?并发负载有研究吗
      

  15.   


    呵呵4个nginx, 5个php-cgf, 开发机器..非服务器不明白这跟数据库负载的关系...并发负载不懂.
      

  16.   

    APC与memcache性能对比,感觉并不怎么真实吧,毕竟各自所擅长的方面不同
      

  17.   

    据说APC只应用于单机
    而memcache则可有单独服务器所以,从这个角度讲memcache或许更快
      

  18.   

    看了你的博文,有几点没看明白,想请你澄清一下:1. 你的博文里说“黑色线为memcache, 蓝色线为apc”,我感觉是说反了,对吗?2. 你给出的每张图,除了“读/写”的区别外,主要是“初始数据条数”不一样,但你的分析中并没有提到这个因素的影响;而反过来,你的结论中“两种运行模式”的差别,在图中看不到。3. 你的结论的第一条,不知是从哪张图上看出来的?(你给出的图,只有一张上出现了交叉)另外,根据你在 9 楼给出的程序代码,我觉得“计时”算法可能会存在很大的舍入误差。如果改成连续操作、首尾计时会更准确一些。
    ■□■□■□■□■□■□■□■
    □             □
    ■  忍以明志 勤以致远  ■
    □             □
    ■□■□■□■□■□■□■□■
    基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)
      

  19.   


    1: 颜色问题, 是正确的. 理论上来讲, APC是要比Memcache快的, 但是, 我的实验结果是在数据量在8万以上, Apc的性能降低了..
    2. 关于图, 其实应该读写各一张就完事了, 不过我用的nginx, 我不会配让他不超时, 就多做了几次出的图, 把读的图连起来, 把写的图连起来, 才能说明问题: 交叉点说明了apc性能低于Memcache的数据量, 而数据量继续增大时, apc性能降低的速度也在降低, 也就是曲线的坡度变缓了..
    3. 由于2所说, 这些图其实本应该是连续的, 所以, 能够证明我的结论1.关于你提到的计时算法, 我觉得这个是没有问题的.
    首先: 由于对APC和memcache都使用了同样的计时, 并且是单次计时, 在几十万次数量下, 可以认为哪怕有影响, 对两者也是均衡的. 所以对于两者的比较结果不会产生影响(这个我总共跑了大概有差不多5, 6次, 结果是一致的.).
    当然, 你提到的首尾计时, 肯定更好, 谢谢.
      

  20.   

    有点明白了,就是说,你给出的图都是 web 环境下的,主要是用来说明 APC 的性能会随着数据存量的增加而下降,当超过 8 万条以后性能就低于 memcache 了。:)关于计时方法的问题,我同意你的观点,应该不至于产生颠覆式的影响。只是有一处特别奇怪,就是你的第一张图,黑线的尖峰很是诡异,这个在你的多次重复实验中也是稳定出现的吗?从你的实验结果看,memcache 在数十万条数据的规模范围内性能表现是比较稳定的,而 APC 则有性能明显下降的趋势。会不会是因为配置差异导致的?毕竟 APC 和 memcache 的设计目标是不同的,也许 APC 根本就不是给这么大量的数据缓存来用的。结合你的另一个实验结论,“在CLI模式下运行, apc性能稳定”,也许可以猜测,APC 在 web 环境下的性能下降是因为资源瓶颈(内存不足)导致的。这个我没有实践经验,纯粹是瞎猜的,hehe■□■□■□■□■□■□■□■
    □             □
    ■  忍以明志 勤以致远  ■
    □             □
    ■□■□■□■□■□■□■□■
    基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)
      

  21.   


    呵呵, 第一张图那个怪异的波动我也没有细究, 呵呵, 只是我们的项目开始使用apc存储了70万条左右的数据, 后来由于要使用一个常驻进程,但又不能和web共享apc, 所以测试了apc和memcache的性能问题, 结果发现数据量大的时候memcache反而快了....
    测完证明了可以用memcache了, 也比较忙, 就没有再继续了, 呵呵....你说的内存不够我觉得有可能, 因为我查资料时候看到apc是mmap的, 而memcache是纯内存, 所以, 有可能是内存不足后使用文件导致的.
      

  22.   

    简单看了一下 APC 的可配置参数,有点小发现,跟你分享一下 :)1. 有一个 apc.enable_cli,似乎是用来让 CLI 程序启用 APC,而想让 CLI 程序跟 web 程序共用缓存的话,也许可以通过指定 apc.mmap_file_mask 来实现;2. apc.user_entries_hint 的缺省配置是 4096,貌似这个 APC 还真不是给“大数据量缓存”来用的。memcache 看上去是个不错的选择,不过如果你有时间有兴趣的话,不妨看看 XCache,也是个不错的东西。■□■□■□■□■□■□■□■
    □             □
    ■  忍以明志 勤以致远  ■
    □             □
    ■□■□■□■□■□■□■□■
    基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)
      

  23.   

    apc.mmap_file_mask  string
        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
    用来决定mmap映射到文件还是共享内存的.apc.user_entries_hint
        这个参数的确是用来调整用户变量缓存数量的, 我刚把这个参数调整到1000000, 跑了50万条, 和CIL模式下运行结果一致.谢谢maquan
      

  24.   

    关于 apc.mmap_file_mask,文档上还有一句 Leaving it undefined will force an anonymous mmap.我理解,如果 anonymous 的话,CLI 跟 web 就可能是各自用自己的缓存了,如果指定了一个名字,也许它们就能共享了呢,还是瞎猜的 :)既然有办法保证 APC 性能不损失,那怎么说也比 memcache 强,除非真有用 memcache 的必要。而我看你前边的介绍,好像打通 CLI/web 共享是一个关键。■□■□■□■□■□■□■□■
    □             □
    ■  忍以明志 勤以致远  ■
    □             □
    ■□■□■□■□■□■□■□■
    基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)
      

  25.   

    APC不能用于频繁写,主要测试读方面性能,这点上是memcached望尘莫及的。