DISCUZ缓存机制

一、DICUZ缓存机制分析:

使用缓存机制的目的很明显,降低服务器性能的消耗,对于常用且变动比较小的数据的数据,可以尽可能的使用缓存来解决,代替最原生的不断的进行数据库查询匹配的过程。而Discuz中提供的数据缓存方式包括内存、数据库、文件三种方式,具体如下。

(1)、项目根目录/config/config_global.php配置数据库/文件缓存方式,当然还有第三种,就是内存缓存。

$_config['cache']['type'] = 'sql';//file

(2)、缓存数据获取:

根目录/source/function/function_core.php:

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 = C::t('common_syscache')->fetch_all($caches);
        foreach($cachedata as $cname => $data) {
            if($cname == 'setting') {
                $_G['setting'] = $data;
            } elseif($cname == 'usergroup_'.$_G['groupid']) {
                $_G['cache'][$cname] = $_G['group'] = $data;
            } elseif($cname == 'style_default') {
                $_G['cache'][$cname] = $_G['style'] = $data;
            } elseif($cname == 'grouplevels') {
                $_G['grouplevels'] = $data;
            } else {
                $_G['cache'][$cname] = $data;
            }
        }
    }
    return true;
}

从函数中可以看出,数据缓存其实相当于把一些常用的数据,通过特定的需求,根据缓存的方式存储于文件 或者 表(前缀)_common_syscache 或者 内存中,当需要使用到某个类型的数据的时候,只需要在代码中加入类似loadcache(‘setting‘);,就可以获取到缓存数据并赋值于自定义全局变量$_G中,即$_G[‘setting‘]; ,其中fetch_all中会判断当前使用的是哪一种缓存方式,如下该函数:

脚本:table_common_syscache.php

public function fetch_all($cachenames) {
        $data = array();
        $cachenames = is_array($cachenames) ? $cachenames : array($cachenames);
        if($this->_allowmem) {
            $data = memory('get', $cachenames);
            $newarray = $data !== false ? array_diff($cachenames, array_keys($data)) : $cachenames;
            if(empty($newarray)) {
                return $data;
            } else {
                $cachenames = $newarray;
            }
        }

        if($this->_isfilecache) {
            $lostcaches = array();
            foreach($cachenames as $cachename) {
                if([email protected]_once(DISCUZ_ROOT.'./data/cache/cache_'.$cachename.'.php')) {
                    $lostcaches[] = $cachename;
                } elseif($this->_allowmem) {
                    memory('set', $cachename, $data[$cachename]);
                }
            }
            if(!$lostcaches) {
                return $data;
            }
            $cachenames = $lostcaches;
            unset($lostcaches);
        }

        $query = DB::query('SELECT * FROM '.DB::table($this->_table).' WHERE '.DB::field('cname', $cachenames));
        while($syscache = DB::fetch($query)) {
            $data[$syscache['cname']] = $syscache['ctype'] ? unserialize($syscache['data']) : $syscache['data'];
            $this->_allowmem && (memory('set', $syscache['cname'], $data[$syscache['cname']]));
            if($this->_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.getglobal('config/security/authkey'))."\n\n$cachedata?>");
                    fclose($fp);
                }
            }
        }

        foreach($cachenames as $name) {
            if($data[$name] === null) {
                $data[$name] = null;
                $this->_allowmem && (memory('set', $name, array()));
            }
        }

        return $data;
    }

当服务器支持使用内存缓存时,使用该方式,DISCUZ代码中默认支持的方式包括redis、memcache、apc、xcache、eaccelerator、wincache这几种,至于使用哪一种,还需要取决于web 服务器支持方式,获取到数据且不空则返回其结果;

当服务器不支持内存缓存时,使用第二种文件缓存,文件缓存会将数据存放于目录./data/cache/ 下,并取名为cache_‘.$cachename.‘.php 
,如果获取到数据且不空,则返回其结果;

而数据库缓存查找操作是在前面两种不支持,或者执行完且数据为空的情况下,根据库缓存从数据库表(前缀)_common_syscache中获取存储数据,其实这里就不能描述为缓存,只是把数据按照一定的格式存放在数据库中,由于其使用其数据的客户端不需要经常实时变动,也就是说可以存在一定的延迟,才使用这样的方式,简化数据库操作,存储方式包括字段缓存变量名(如setting)、缓存类型(0,1是否为序列化数据)、缓存时间、缓存数据。

当执行了数据库查询操作之后,如果检测到存在内存缓存or文件缓存,由于从前面逻辑可以判断,如果支持该两种缓存方式,能够执行数据库查询操作是因为该两种缓存方式缓存的数据为空,这个时候就需要将数据库查询到的数据缓存到内存缓存或者文件缓存中。(这里就是文件缓存数据生成的位置,而数据缓存生成的数据则存放与./data/cache/目录下)

(3)、缓存数据生成:(文件缓存数据根据数据是否需要缓存,且支持文件缓存,会在数据获取的过程中存储于缓存文件中,缓存文件中如果存在数据的话,则不会从数据库中获取数据,具体详情如“缓存数据获取”中有所描述)

数据库缓存生成:

方式一:

根目录/source/function/function_core.php,直接数据库缓存数据的存储:

function savecache($cachename, $data) {
    C::t('common_syscache')->insert($cachename, $data);
}

function save_syscache($cachename, $data) {
    savecache($cachename, $data);
}

很简单,把需要缓存的数据直接存储于需要的位置中(内存、文件、数据库),如下insert操作:

public function insert($cachename, $data) {

        parent::insert(array(
            'cname' => $cachename,
            'ctype' => is_array($data) ? 1 : 0,
            'dateline' => TIMESTAMP,
            'data' => is_array($data) ? serialize($data) : $data,
        ), false, true);

        if($this->_allowmem && memory('get', $cachename) !== false) {
            memory('set', $cachename, $data);
        }
        $this->_isfilecache && @unlink(DISCUZ_ROOT.'./data/cache/cache_'.$cachename.'.php');
    }

存储数据将存放于缓存数据库中,内存中,以及删除原始的缓存文件(目的请参照缓存数据获取时文件缓存的生成过程,当文件缓存数据为空时,会重新生成文件缓存数据)

方式二:

即使用function_cache.php脚本中的updatecache($cachename)函数,该函数的实现机制协同项目目录./source/function/cache/cache_*.php脚本。

而./source/function/cache/cache_*.php脚本最终的依然是调用save_syscache函数,所以,为了方便数据格式化,在需要存储特定数据的时候,可以在./source/function/cache/目录下创建相应的数据生产脚本文件,该脚本会通过原有的逻辑,通过调用updatecache(‘特定标示符‘) 函数,然后调用cache_特定标示符.php脚本生成缓存数据,缓存数据的存放根据系统设定好的缓存方式进行存储。

************************************************************

二、Discuz官方提供“Discuz缓存机制”——原文:http://bbs.zb7.com/discuz/dx25/plug/construct/construct_cache.htm

Discuz! X2.5 的 config_global.php 中有这样一行代码

$_config[‘cache‘][‘type‘] = ‘sql‘;

这就是 Discuz! 内置的缓存方式,如果填写 ‘sql‘ 则为使用数据库缓存,填写 ‘file‘ 则为使用文件缓存。

内存级缓存

缓存层的引入是为了解决MYSQL自身对高并发处理的性能瓶颈,目前产品缓存层采用主流的Key-Value对形式,内存级的缓存产品很多,支持的内存优化接口有 Memcache、eAccelerator、Alternative PHP Cache(APC)、Xcache、Redis 五种,优化系统将会依据当前服务器环境依次选用接口,单服务器环境中推荐使用APC,多服务器环境中推荐使用Redis或Memcache。

数据层是以表为单位的类文件,所有表类都继承discuz_table基类,基类实现缓存操作的相关函数;理论上所有的数据表均可以缓存,目前产品在六个压力大的数据表内置开启了缓存机制:用户相关表、回帖、主题、主题和专辑关系、淘贴专辑、用户关注关系。

  • 用户相关表

缓存表:‘common_member‘, ‘count‘, ‘status‘,‘profile‘, ‘field_home‘, ‘field_forum‘。

UID为缓存KEY。表数据更新时缓存数据会同步更新。

  • 回帖

以TID为单位,缓存第一页的post数据。表数据更新时缓存数据会同步更新。

  • 主题

TID为缓存KEY。表数据更新时缓存数据会同步更新。

版块列表默认参数第一页时以 forumdisplay_FID 为缓存KEY,缓存时间内数据不更新。

  • 主题和专辑关系

以TID为单位,此TID的专辑ID集合,表数据更新时缓存数据会同步更新。

  • 淘贴专辑

以TID为单位,此TID的专辑集合,缓存时间内数据不更新。

  • 用户关注关系

以UID为单位,此UID关注用户的关系数据,缓存时间内数据不更新。

内存级缓存层实现细节

  • discuz_table基类中缓存机制的实现
 /**
* @var string 缓存主键名前缀,为空时表示此表不支持缓存
*/
protected $_pre_cache_key; 

/**
* @var string 缓存时间,以秒为单位,0表示永久或相关配置文件中的默认值
*/
protected $_cache_ttl; 
  • discuz_table基类中缓存机制的方法
//缓存一个变量到缓存中,如果 KEY已经在则会被覆盖为新值
store_cache($id, $data, $cache_ttl = null, $pre_cache_key = null)
//获取指定KEY的缓存数据
fetch_cache($ids, $pre_cache_key = null)
//清除指定KEY的缓存
clear_cache($ids, $pre_cache_key = null)
//更新一个已经存在的KEY,只更新修改的字段
update_cache($id, $data, $cache_ttl = null, $pre_cache_key = null)
//批量更新缓存,只更新已经存在KEY的指定修改的字段
update_batch_cache($ids, $data, $cache_ttl = null, $pre_cache_key = null)
//重置已经存在的KEY的值
reset_cache($ids, $pre_cache_key = null)
//累加缓存数据中某字段的值
increase_cache($ids, $data, $cache_ttl = null, $pre_cache_key = null)
时间: 2024-08-08 05:36:02

DISCUZ缓存机制的相关文章

浏览器缓存机制浅析

非HTTP协议定义的缓存机制 浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如: Expires: Cache-control等).但是也有非HTTP协议定义的缓存机制,如使用HTML Meta 标签,Web开发者可以在HTML页面的<head>节点中加入<meta>标签,代码如下: <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> 上述代码的作用是告诉浏览器当前页面不被缓存,每

Hibernate 缓存机制

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的

Android开源框架ImageLoader:加载图片的三级缓存机制

前言:可从  https://github.com/nostra13/Android-Universal-Image-Loader 下载三级缓存机制的开源框架.下文简单介绍该框架中主要的常用方法,掌握这些方法,基本就可应对多数图片下载的需求. 注意:以下代码为示意代码片断,仔细读一下应能知道怎么用.蓝色表示为开源框架中的类. 1.初始化ImageLoader类对象: ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.

Varnish缓存机制详细介绍及简单配置

Varnish是一款高性能的开源HTTP加速器,其主要用来做为反向代理中的缓存服务器使用,但其实Varnish本身也是具有反向代理功能的,但在创建连接和维持连接上,与Nginx相比差距很大,现在有一个很流行的架构就是前端用Nginx作为反向代理,后面加Varnish缓存服务器为Web服务加速 在将Varnish前先谈谈我们的浏览器缓存机制,现在的浏览器基本都具有缓存功能,它能将我们以前访问过的静态内容和可进行缓存的动态内容缓存再本地,而后在下次访问相同资源时,如果可以确认Server端的资源未发

【腾讯Bugly干货分享】彻底弄懂 Http 缓存机制 - 基于缓存策略三要素分解法

本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/qOMO0LIdA47j3RjhbCWUEQ 作者:李志刚 导语 Http 缓存机制作为 web 性能优化的重要手段,对从事 Web 开发的小伙伴们来说是必须要掌握的知识,但最近我遇到了几个缓存头设置相关的题目,发现有好几道题答错了,有的甚至在知道了正确答案后依然不明白其原因,可谓相当的郁闷呢!!为了确认下是否只是自己理解不深,我特意请教了其他几位小伙

hibernate缓存机制详细分析 复制代码

您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内容有任何疑问, 可以通过评论或发邮件的方式联系我: [email protected] / [email protected] 如果需要转载,请注明出处,谢谢!! 在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session级别).二级缓存(sessionFactory级别)以

Java缓存学习之三:CDN缓存机制

CDN是什么? 关于CDN是什么,此前网友详细介绍过. CDN是Content Delivery Network的简称,即"内容分发网络"的意思.一般我们所说的CDN加速,一般是指网站加速或者用户下载资源加速. 举个通俗的例子: 谈到CDN的作用,可以用8年买火车票的经历来形象比喻:8年前,还没有火车票代售点一说,12306.cn更是无从说起.那时候火车票还只能在火车站的售票大厅购买,而我所住的小县城并不通火车,火车票都要去市里的火车站购买,而从县城到市里,来回就是4个小时车程,简直就

10.hibernate缓存机制详细分析(转自xiaoluo501395377)

hibernate缓存机制详细分析 在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session级别).二级缓存(sessionFactory级别)以及查询缓存,当然还要讨论下我们的N+1的问题. 随笔虽长,但我相信看完的朋友绝对能对hibernate的 N+1问题以及缓存有更深的了解. 一.N+1问题 首先我们来探讨一下N+1的问题,我们先通过一个例子来看一下,什么是N+1问题: list()获得对象: 1 /** 2 * 此时会发出一条sql,将30个学生全部查询出来

浏览器缓存机制

最近在做项目过程中需要对部分文件数据进行缓存,于是整理一些关于浏览器缓存机制的信息 概要总结:1.Expires 过期时间2.Cache-Control 缓存机制 [max-age=300]缓存时间 300 表示5分钟3.Last-Modified 最后修改时间 对应在请求头部有If-Modified-Since4.Etag 唯一标识 由服务器生成 对应在请求头部有If-No-Match优先级:Etag > last-modified > Expires 浏览器缓存机制,其实主要就是HTTP协