缓存__Discuz X缓存机制浅析
来源:互联网 发布:三位一体2mac中文补丁 编辑:程序博客网 时间:2024/06/04 18:48
第二版
首发于:http://www.PHPig.net,转载请注明。
Discuz X中,缓存核心函数在function_core.php和function_cache.php中。其中以updatecache和loadcache两个函数最为核心。弄清楚了这两个函数之后,完全能剥离出来自己用,或者仿它的写法自己创建缓存了。
这里简单叙述一下X里面,缓存的机制。
X的缓存,主要是存储不经常变动的数据,存储方式可以选择数据库,或者文件。下面举例说明。我们可以在后台的admincp_click.php,看到 updatecache('click'),证明click是使用了缓存机制的。Click就是表态图标,头像什么的信息,路过,雷人,鸡蛋等等,这些信息是基本不修改的,并且会在前台很多地方用到。而如果不使用缓存的话,则每次都需要遍历一次click表,而如果有100个表态图像的话则会读100次库,每篇日志都会有click信息,如果有100篇日志则会读click表10000次。
X的做法就是,把类似click表的内容,序列化,存放在common_syscache表中,这样每次只需要读一次库,或者存放在文件中,每次都读这个文件。下面我们详细看看代码是怎么运行的。我们这里模拟一个需要缓存的表message,只有两个字段,subject和content。当然 message这样的经常更新的数据是不适合缓存的,这里只是举例方便。
Discuz X中,缓存核心函数在function_core.php和function_cache.php中。其中以updatecache和loadcache两个函数最为核心。弄清楚了这两个函数之后,完全能剥离出来自己用,或者仿它的写法自己创建缓存了。
这里简单叙述一下X里面,缓存的机制。
X的缓存,主要是存储不经常变动的数据,存储方式可以选择数据库,或者文件。下面举例说明。我们可以在后台的admincp_click.php,看到 updatecache('click'),证明click是使用了缓存机制的。Click就是表态图标,头像什么的信息,路过,雷人,鸡蛋等等,这些信息是基本不修改的,并且会在前台很多地方用到。而如果不使用缓存的话,则每次都需要遍历一次click表,而如果有100个表态图像的话则会读100次库,每篇日志都会有click信息,如果有100篇日志则会读click表10000次。
X的做法就是,把类似click表的内容,序列化,存放在common_syscache表中,这样每次只需要读一次库,或者存放在文件中,每次都读这个文件。下面我们详细看看代码是怎么运行的。我们这里模拟一个需要缓存的表message,只有两个字段,subject和content。当然 message这样的经常更新的数据是不适合缓存的,这里只是举例方便。
function updatecache($cachename = '') { global $_G; static $cachelist = array(''message); //把需要缓存的数据名,可自己添加。 $updatelist = empty($cachename) ? $cachelist : (is_array($cachename) ? $cachename : array($cachename)); foreach($updatelist as $value) { getcachearray($value); //填充缓存数据 }
这里看看getcachearray()代码
function getcachearray($cachename, $script = '') { global $_G; $cols = '*'; $conditions = ''; $timestamp = TIMESTAMP; switch($cachename) { //根据缓存名称按要求写相关代码,什么需要缓存,什么不需要缓存,我这里的conditions用默认的,就是缓存全部数据。 case 'message': $table = 'message'; break; ………… } $data = array(); $query = DB::query("SELECT $cols FROM ".DB::table($table)." $conditions"); //读库,存为数组。 switch($cachename) { case 'message': while($row = DB::fetch($query)) { $data['subject'][$row['id']] = $row['subject']; $data['content'][$row['id']] = $row['content']; $data['dateline'][$row['id']] = $row['dateline']; } save_syscache($cachename, $data); //序列化存到syscache表中。 return true; }
看看save_syscache()是干嘛的。
function save_syscache($cachename, $data) { static $isfilecache, $allowmem; if($isfilecache === null) { $isfilecache = getglobal('config/cache/type'); //取缓存类型,是file,还是sql。 $allowmem = memory('check'); //判断是否使用Memcached } if(is_array($data)) { $ctype = 1; $data = addslashes(serialize($data)); //序列化 } else { $ctype = 0; } //入库 DB::query("REPLACE INTO ".DB::table('common_syscache')." (cname, ctype, dateline, data) VALUES ('$cachename', '$ctype', '".TIMESTAMP."', '$data')"); //memcached启用的话,清空缓存 $allowmem && memory('rm', $cachename); //缓存file存在的话,删除文件 $isfilecache && @unlink(DISCUZ_ROOT.'./data/cache/cache_'.$cachename.'.php');}
总结一下updatecache()的作用,读原始库,这里是message表,序列化存到syscache表的一条记录,并且清空memcached缓存和缓存的file。
Updatecache => getcachearray => save_syscache
下面我们研究缓存模块的下半部分,loadcache();
function loadcache($cachenames, $force = false) { global $_G; static $loadedcache = array(); $cachenames = is_array($cachenames) ? $cachenames : array($cachenames); $caches = array(); foreach ($cachenames as $k) { if(!isset($loadedcache[$k]) || $force) { $caches[] = $k; $loadedcache[$k] = true; } }if(!empty($caches)) { $cachedata = cachedata($caches); //读数据库缓存或者file缓存 foreach($cachedata as $cname => $data) { $_G['cache'][$cname] = $data; $cachearr = $_G['cache'][$cname]; } } return $cachearr;
function cachedata($cachenames) { static $isfilecache, $allowmem; if($isfilecache === null) { $isfilecache = getglobal('config/cache/type') == 'file'; $allowmem = memory('check'); } $data = array(); $cachenames = is_array($cachenames) ? $cachenames : array($cachenames); if($allowmem) { $newarray = array(); foreach ($cachenames as $name) { $data[$name] = memory('get', $name);//通过memcached取值 if($data[$name] === null) { $data[$name] = null; $newarray[] = $name; } } if(empty($newarray)) { return $data; } else { $cachenames = $newarray; } } if($isfilecache) { $lostcaches = array(); foreach($cachenames as $cachename) { //这里include缓存file if(!@include_once(DISCUZ_ROOT.'./data/cache/cache_'.$cachename.'.php')) { $lostcaches[] = $cachename; } }//如果已经有file,则不走$lostcaches[] = $cachename,$lostcaches没值,直接return file中的$data。 if(!$lostcaches) { return $data; } $cachenames = $lostcaches; unset($lostcaches); } $query = DB::query("SELECT /*!40001 SQL_CACHE */ * FROM ".DB::table('common_syscache')." WHERE cname IN ('".implode("','", $cachenames)."')"); while($syscache = DB::fetch($query)) { $data[$syscache['cname']] = $syscache['ctype'] ? unserialize($syscache['data']) : $syscache['data'];//通过memcached存到内存里 $allowmem && (memory('set', $syscache['cname'], $data[$syscache['cname']]));//创建file,数据存到file中 if($isfilecache) { $cachedata = '$data[\''.$syscache['cname'].'\'] = '.var_export($data[$syscache['cname']], true).";\n\n"; if($fp = @fopen(DISCUZ_ROOT.'./data/cache/cache_'.$syscache['cname'].'.php', 'wb')) { fwrite($fp, "<?php\n//Discuz! cache file, DO NOT modify me!\n//Identify: ".md5($syscache['cname'].$cachedata)."\n\n$cachedata?>"); fclose($fp); } } } foreach ($cachenames as $name) { if($data[$name] === null) { $data[$name] = null; $allowmem && (memory('set', $name, array())); } } return $data;}
- 缓存__Discuz X缓存机制浅析
- 内存缓存__discuz缓存机制(内存缓存,memory())
- 缓存__Discuz!X 中会自动初始化的一些系统缓存
- IE缓存机制浅析
- Browser缓存机制浅析
- 浅析hibernate缓存机制
- iOS 缓存机制浅析
- 浏览器缓存机制浅析
- 浏览器缓存机制浅析
- 浏览器缓存机制浅析
- 浏览器缓存机制浅析
- Web缓存机制浅析
- 浏览器缓存机制浅析
- Hibernate 缓存机制浅析
- iOS 缓存机制浅析
- H5 缓存机制浅析
- <MyBatis缓存机制>一级缓存源码浅析
- Glide缓存机制源码浅析
- 自我介绍
- 信号与系统2:正弦信号和指数信号
- Mac中直接打开隐藏的文件或文件夹
- linux 强杀进程
- RPC远程调用编程 (1)
- 缓存__Discuz X缓存机制浅析
- ios中摄像头/相册获取图片,压缩图片,上传服务器方法总结
- 一个很炫的css3动画做的jquery.loding等待加载插件
- 面向对象
- HttpURLConnection学习
- 【Android开发辅助利器】Android4.1 Document(CHM)格式
- Android权限Uri.parse的详细资料
- POJ 1789 Truck History
- 关于navicat连接oracle10g 报 ORA-12737 set CHS16GBK错误的解决方案