第二版
首发于: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这样的经常更新的数据是不适合缓存的,这里只是举例方便。
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;
}
分享到:
相关推荐
base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz
ZZ561401.CAB ZZ561401.CAB ZZ561401.CAB
wincc SIMATIC WinCC是第一个使用最新的32位技术的过程监视系统,具有良好的开放性和灵活性。 从面市伊始,用户就对SIMATIC WinCC印象深刻。
在CAD中想要快速测量长度,在CAD工具栏找到加载应用程序,再点击加载 加载成功后在输入栏输入“zz”(不分大小写)在选择你需要测量的线段即可。
我们研究了四轻子最终状态ℓ+ℓ-ℓ+ℓ-的产生,这些状态主要由一对弱电Z玻色子ZZ产生。 使用LoopSim方法,我们合并ZZ和ZZ + jet的NLO QCD结果,并获得ZZ产生的近似NNLO预测。 还包括对ZZ过程的精确胶子融合环平方的...
,主图指标,顶底信号,突破,转折信号,都很明显
EMQ X (Erlang/Enterprise/Elastic MQTT Broker) 是基于 Erlang/OTP 平台开发的开源物联网 MQTT 消息服务器。Erlang/OTP 是出色的软实时(Soft-Realtime)、低延时(Low-Latency)、分布式(Distributed) 的语言平台。...
TZ200XSQ-ZZ3D_id2434_x_t.prt
程序员的编辑器——VIM(zz) - 饮水思源
留言本改自柏图留言本 BTB 1.2 管理员:zz809 密 码:zz809.com
zz_layer.il是源代码,install.bat是安装的 使用举例:zz 1-3 4 126 127 层号定义,与PADS类似:1~120是etch ;SolderMask: 121(top) 128(bot) ;Silkscreen: 126(top) 129(bot) ;Assembly: 127(top) 130(bot) ;Paste...
ZZ公司安全生产守则.docx
华为铁三角组织-运作机制与激励方式zz.pptx
基于国家标准的endnote的输出样式,适用于学生党论文插入文献参考,较为方便。endnote论文神器。
zz;ldkfjntmtmsbggyyessdd
ZZ-2021030 网络搭建与应用赛项赛卷《网络环境》.pdf
android应用源码zz-doctor中医大夫助理信息系统
ZZ Fibo Trader 简单地展示了 Simple ZZ Fibo 的使用, 它在之字转向的波动中绘制斐波那契线。另外,算法还展示了通过抛物线系统进行移动止损的操作。
cad标高归零,好用的