您现在的位置是:首页 > cms教程 > Discuz教程Discuz教程
discuz缓存机制分析介绍
雨寒2025-06-28Discuz教程已有人查阅
导读使用缓存机制的目的很明显,降低服务器性能的消耗,对于常用且变动比较小的数据的数据,可以尽可能的使用缓存来解决,代替最原生的不断的进行数据库查询匹配的过程。
一、 discuz缓存机制分析:
使用缓存机制的目的很明显,降低服务器性能的消耗,对于常用且变动比较小的数据的数据,可以尽可能的使用缓存来解决,代替最原生的不断的进行数据库查询匹配的过程。而Discuz中提供的数据缓存方式包括内存、数据库、文件三种方式,具体如下。
(1)、项目根目录/config/config_global.php配置数据库/文件缓存方式,当然还有第三种,就是内存缓存。$_config['cache']['type'] = 'sql';//file
(2)、缓存数据获取:
根目录/source/function/function_core.php:
脚本:table_common_syscache.phppublic
当服务器不支持内存缓存时,使用第二种文件缓存,文件缓存会将数据存放于目录 ./data/cache/ 下,并取名为 cache_' .$cachename . '.php ,如果获取到数据且不空,则返回其结果;
而数据库缓存查找操作是在前面两种不支持,或者执行完且数据为空的情况下,根据库缓存从数据库表(前缀)_common_syscache中获取存储数据,其实这里就不能描述为缓存,只是把数据按照一定的格式存放在数据库中,由于其使用其数据的客户端不需要经常实时变动,也就是说可以存在一定的延迟,才使用这样的方式,简化数据库操作,存储方式包括字段缓存变量名(如setting)、缓存类型(0,1是否为序列化数据)、缓存时间、缓存数据。
当执行了数据库查询操作之后,如果检测到存在内存缓存or文件缓存,由于从前面逻辑可以判断,如果支持该两种缓存方式,能够执行数据库查询操作是因为该两种缓存方式缓存的数据为空,这个时候就需要将数据库查询到的数据缓存到内存缓存或者文件缓存中。(这里就是文件缓存数据生成的位置,而数据缓存生成的数据则存放与./data/cache/目录下)
(3)、缓存数据生成:(文件缓存数据根据数据是否需要缓存,且支持文件缓存,会在数据获取的过程中存储于缓存文件中,缓存文件中如果存在数据的话,则不会从数据库中获取数据,具体详情如“缓存数据获取”中有所描述)
数据库缓存生成:
方式一:
根目录/source/function/function_core.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缓存机制”
Discuz! X2.5 的 config_global.php 中有这样一行代码
缓存层的引入是为了解决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基类中缓存机制的实现
使用缓存机制的目的很明显,降低服务器性能的消耗,对于常用且变动比较小的数据的数据,可以尽可能的使用缓存来解决,代替最原生的不断的进行数据库查询匹配的过程。而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.phppublic
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(!@include_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缓存机制”
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)
本文标签:
很赞哦! ()
图文教程
ecshop整合discuz的方法
实际应用背景:网站使用ecshop已经有一段时间,积累了一些用户,discuz是新装.希望把ecshop的用户导入discuz,并能实现同步登录。
Discuz常见问题制作一个独立页面
首先参考Discuz如何自定义单个页面的文章,确保你已经能做一个"关于我们"这种纯HTML静态页面(只有文字和静态图片描述)。其次参考下面的文件修改原来的htm文件
忘记UCENTER创始人密码怎么办,discuz密码找回方法
人们都是健忘的,何况每天的事情很多,有些站长更是做,赚点外快而已,而ucenter更是不常用,所以忘记密码是在正常不过的事情,如果密码忘记怎么找回呢?方法有很多种
Discuz安装部署教程
说明:本文档用于帮助您全新安装完整的 Discuz! X 社区软件,适用于 Discuz! X2 系列版本(beta、RC、正式版)。一、下载 Discuz! X 官方版到本地或者服务器上
相关源码
-
(自适应响应式)宠物经验资讯咨询博客pbootcms网站源码下载除宠物资讯领域外,通过内容替换可快速适配宠物用品商城、宠物医疗咨询平台、宠物训练教程网站、动物保护组织官网、水族爱好者社区等垂直领域。查看源码 -
(自适应)绿色农业大型机械设备展示网站模板下载基于PbootCMS内核深度定制开发的农业机械行业专用模板。针对农机设备展示、产品参数说明等需求优化设计,突出农业机械行业特性查看源码 -
(PC+WAP)高端餐饮美食小吃加盟网站模板下载pbootcms本模板基于PbootCMS内核开发,为餐饮美食品牌加盟、小吃连锁企业量身打造。通过精致的美食视觉呈现与加盟业务流程展示,帮助餐饮企业建立专业线上门户,实现品牌形象与加盟业务的双重展示。查看源码 -
(自适应)电梯扶梯升降梯行业pbootcms企业网站模板(自适应手机版)响应式电梯扶梯类pbootcms模板 电梯生产企业绿色企业网站源码下载PbootCMS内核开发的网站模板,该模板适用于电梯、扶梯类等企业,查看源码 -
(PC模板)工商公司注册会计财务记账pbootcms模板源码下载基于PbootCMS的工商财税行业网站系统,手工编写前端代码确保执行效率,双端自适应设计,支持后台实时更新服务价格和政策文件。查看源码 -
自适应手机版五金机械阀门设备通用行业网站模板该PbootCMS内核开发的网站模板适用于阀门设备、五金机械类企业,通过更换文字图片也可快速适配其他工业领域。采用响应式设计,确保PC端与手机端数据同步,操作便捷,并附带测试数据。查看源码
| 分享笔记 (共有 篇笔记) |
