Discuz缓存机制分析

缓存技术,不管从前还是现在,从来都是被一些cms或其他系统所重视的,从速度,从效率,没有理由不使用缓存..... 在《对PHP缓存的初识》一文中说过一点关于缓存的东西,那篇文章主要说的是一个检查访问者的IP是否被封的例子,按照水水说的应该属于“生成缓存文件”这一类。而今天我要总结的是另一个层次上的缓存应用。
在discuz里面有一个forumdate文件夹,这个是论坛记录和缓存文件的存放目录,一般这些文件都是自动生成的,我们关心的是其中的缓存文件,在./forumdate/cache/里面存储的都是一些discuz!的基本设置和一些常量(一般在 $_DCACHE),比如《对PHP缓存的初识》一文中举的判断IP是否被BAN就属于discuz!的基本设置,在./forumdate/template目录下即缓存着已经预编译好的模板文件,想一下,在第一次装上discuz论坛系统打开首页时是不是有类似“缓存文件建立成功,请刷新”的提示,那就是第一次执行缓存动作,生成. /forumdate/template目录下的东西。
     在这里,我先大致介绍下流程吧,在用户请求一个页面时,程序会首先到./forumdate/template看一下有没有预编译好的文件,如果有的话,则直接拿来用,如果没有或者缓存过期的话则重新编译,生成文件缓存在./forumdate/template里,想一下phplib模板的处理方式,每次请求页面时都要用正则的方式来匹配模板,而在discuz!的处理机制中是先用正则匹配模,预编译好放在缓存文件中,每次用户请求页面就直接从缓存中提取,时间,效率自然就来了吧!
    看下例如index.php,member.php下面都有个include template('XXX');在./include/global.func.php里有template()这个函数,在template函数里又调用到parse_template()这个函数,另外在cache.func.php中还有一个长达1528的程序,这些程序是怎么运转的呢? discuz的缓存机制是怎样处理每一个细节上的问题的呢?

打开leftmenu.php,为什么拿这个为例子呢,因为它简单明了能说明问题(某位同学教我时也是拿这个为例子的)。
         在最下面有一句include template('leftmenu');,刚看到这一句感到很纳闷,include还可以包含一个函数??再打开./include/global.func.php里面的template()这个函数,return $objfile;而在前面有一个$objfile =discuz_ROOT.'./forumdata/templates/'.$templateid.'_'.$file.'.tpl.php';   这时候才明白,template返回的是这个文件的地址,而这个文件就是上文我们说的“预编译好的文件”,在最后面加上include template('leftmenu');,就是为了把这个预编译好的文件包含近来,在leftmenu.php中可以看到在include template('leftmenu');之前是没有任何输出的,所有的输出就是$objfile这个文件,那么就按template()这个函数返回的地址找到这个文件,可以看到是一个html夹杂着<? xxx  ?>的文件,大家刚学PHP做个留言板或记数器的时候就是写的这样的吧!那为什么最后要的还是这种文件呢?原因很简单---这样做执行速度快而且在前面已经分离了美工和程序!这里和像phplib这种模板引擎的区别在上文也提到了。或许你又会有疑问了,为什么不直接生成静态页面呢,这样做速度不是更快吗?是的,生成静态的是很快,但是你要知道这是一个论坛系统,变化的批频率是相当高的,每次变化都要重新生成静态文件,想一下这是多么大的开销啊!个人认为在一些不是经常变化的CMS或这单存的文章发布系统比较适合生成静态文件。
     在template()函数中有这样一段
复制内容到剪贴板
代码:
1.  if($tplrefresh == 1 || ($tplrefresh > 1 && substr($GLOBALS['timestamp'], -1) > $tplrefresh)) {  
   2.     //如果模板已经修改了,则重新编译  
   3.     if(@filemtime($tplfile) > @filemtime($objfile)) {  
   4.         require_once discuz_ROOT.'./include/template.func.php';  
   5.         parse_template($file, $templateid, $tpldir);  
   6.     }  
   7. }
$tplrefresh这个变量为模板自动刷新的开关,这段代码的意思是在社会子模板自动刷新的前提下,如果模板文件已经修改了,则重新编译生成缓存文件存在./forumdata/template/下,从这儿也能看到效率.......
    在上个代码块中提到parse_template()这个函数,在这里先简单介绍下吧!这个函数是discuz的核心函数,就是用来编译模板文件的,在处理机制上这个函数基本原理和其他的模板类大同小异,用正则对模板进行匹配,不同的是
复制内容到剪贴板
代码:
1.  if(!@$fp = fopen($objfile, 'w')) {  
   2.         dexit("Directory './forumdata/templates/' not found or have no access!");  
   3.     }  
   4. ....  
   5. ....  
   6. flock($fp, 2);  
   7.     fwrite($fp, $template);  
   8.     fclose($fp);
这段代码的意思就是将编译好的模板文件存到./forumdata/template/下面,关于这个其模板机制也没必要做过多介绍,与本问主题关系不大。

最后用一张图来看下吧!

你可能感兴趣的:(Discuz缓存机制分析)