May 14th, 2008 by 张磊
blog的服务器搬家之后我就尝试了WP-Cache和WP-SuperCache,它们的共同问题是启用插件后,我在后台打开它们的管理界面,只能看到空白,某个函数可能在执行过程中被终止了。 可是WP生成一个页面要查询几十次数据库,这个着实很汗颜。后来我用了Cos-HTML-Cache,但一味地生成HTML,虽然负载低了,灵活性降低很多。今天脑袋里灵光一闪,想自己写一个基于memcached的WP插件(服务器上有memcached)。于是打开WP-SuperCache想看看他的实现,顺手调试了一下。没想到这一下就发现了问题,不出所料,确实是程序莫名终止了。 if ( !wp_cache_check_link() || !wp_cache_verify_config_file() || !wp_cache_verify_cache_dir() ) { echo “<br>Cannot continue… fix previous problems and retry.<br />”; echo “</div>\n”; return; } 里面有这么一段,看样子是用来验证一些东西。我直接把这段注释掉,WP-SuperCache后台就可以打开了。后面都很顺利,现在WP-SuperCache工作很正常。 大致浏览了一下,程序里很多判断都可以去掉(前提是你很了解它的原理了)。阉割之后,应该还会快一些呢。
April 28th, 2008 by 张磊
niupu缓存策略的使用上,为了省力用了Zend_Cache中的PageCache。而使用PageCache时,对于不同的登录用户,可能有一些细节是不一样,所以选择了“cache_with_cookie”和”make_id_with_cookie”。这样的话,程序会先对cookie数组进行序列化,将其转化为字符串,然后与REQUEST_URI拼接,最后计算md5散列值。计算得到的结果就是这个PageCache的ID。 对于一般的爬虫们发起的请求,自然是不带有Cookie的,也可以容易地使用缓存。但通过Firefox打开网站,在使用帐户登录以前,我也以为是不带有Cookie、可以使用缓存的。但实际情况是一直都不能成功使用缓存,以为是个案,所以没有管。直到前些日子用了memcached,又忍不住开工调试。 最后发现是cookie中的 AJSTAT_ok_times和AJSTAT_ok_pages在捣乱。在我没做任何设置时,这两个值就随着我访问网站出现在cookie列表里。我仔细搜索也没找到关于这两兄弟的细节,比如为啥会自己出现在cookie中。不过我猜测ok_times应该是记录访问这个网站的次数,ok_pages用来记录访问的页数,不知道是不是正确。 找到了问题,就可以有针对性地做出修改了。比较好的办法是写一个新的类继承原有的类,然后重写一下make_id这个函数。不过我就直接改了Zend_Cache的源码。 在/Cache/Frontend/Page.php中,有个叫“_makePartialId”的函数,找到包含case = “Cookie”的一节,其中有一句: $var = $_COOKIE; 改成 $var = array($_COOKIE['info1'],$_COOKIE['info2']…); 原理就是用一个类似filter 的东西把有效的Cookie信息进行重新打包成一个数组。这样就不会把那些没用的Cookie信息也一并序列化了。 虽然问题解决了,可是还是没弄明白 AJSTAT_ok_times和AJSTAT_ok_pages到底是怎么生出来的。
June 8th, 2007 by 张磊
今天尝试着在牛扑的三个页面上用了缓存:tag页面,分类页面以及图书信息页面。中午没吃饭,把它搞了出来。刚刚放上去的时候,缓存之后的页面效率很高,基本上比原来的查询提高了一个数量级。 但是下午出去办了很多事情,晚上和徐老师聊了很久,再回来看牛扑,程序的效率已经让我惨不忍睹。一个简单的图书信息页面都在几十秒才能出来,而且是使用缓存之后──为什么呢? 原因在于缓存的文件太多了。 现在那个缓存目录下,大概有几万个文件。想像一下ZendCache需要在这几万个文件中准确找出那个对应的缓存文件,然后判断它是不是过期了,这中间的开销不亚于从百万级别的数据库中来检索(因为数据库的检索是可以进行优化的)。 现在那里边的文件已经多到我使用rm命令都删除不了了,相当恐怖。 当然,上次PHP之父Rasmus 说,缓存可以有很多层次。其实用ZendCache适合做通用的缓存,在缓存内容比较少的时候效率提升很明显。但是文件数目的增多会使效率急剧下降,所以,控制一个较短的lifetime可以算一个解决的办法了。 另外,牛扑上的图书目录所用的缓存就很稳定。看来这些东西还是应该自己好好去实践一下。通用的缓存架构不一定是提升效率的稻草。
June 7th, 2007 by 张磊
最近在研究PHP中的缓存,在牛扑上一个简单的图书信息页面(比如这个)都要进行至少9次数据库查询,而其中大部分东西都是在相当长一段时间不会变的,所以把这些内容缓存出来是很必要的。其实现在的牛扑一部分内容是有缓存的,当然效果很好,但缓存没有大规模使用,会限制整站的速度。于是我开始找一种通用的缓存机制,果然被我找到了,那就是ZF中的Zend_Cache。 其实缓存的概念在很多地方都有,CPU中有一级缓存二级缓存,缓存的存在大大提高了信息交换的速度(当然,和命中率有关),其实是一种空间换时间的办法。空间换时间的思路在编程中也有,特别是在做ACM时,对解法要求的效率很高,这些时候“空间换时间”的思想往往会对解题有很大帮助。 Zend_Cache是包含在ZendFramework中的,我查看了一下官方文档,发现介绍的比较简单。后来找到了Babel的程序,才看到了实例。V2EXCore.php中有这样一段: if ($o = $this->cs->get(‘babel_top_wealth’) && $cached) { echo $o; } else { ob_start(); /*output sth.*/ $o = ob_get_contents(); ob_end_clean(); $this->cs->save($o, ‘babel_top_wealth’); echo $o; } 其中$this->cs是一个初始化好的缓存类。在这里,思路是这样,如果缓存”babel_top_wealth”命中,就输出,如果没有命中,就通过ob_start()/ob_get_contents()获得输出的内容,然后保存到缓存。坦白说,这个比我以前自己写的缓存类好使多了。 现在唯一的问题是,缓存很多的话查找也是一个问题。牛扑上的50W本书假如有10W本进入缓存,估计需要的空间在1G左右。这个时候,到底是数据库的速度快呢,还是利用程序的逻辑从磁盘上读的速度快呢?