Discuz X缓存机制源代码浅析

1.更新缓存的php代码

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); //填充缓存数据
    } 

  

2.获取缓存的数组php代码

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; 
}

  

3.保存系统缓存

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缓存和缓存的fil​e。
Updatecache => getcachearray => save_syscache

下面我们研究缓存模块的下半部分,loadcache();

4.载入缓存

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; 

  

5.缓存数据

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;
} 

  

posted @ 2013-06-24 14:16  编程狂热者  阅读(457)  评论(0编辑  收藏  举报