您现在的位置是:首页 > 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)
本文标签:
很赞哦! ()
图文教程
Discuz公共样式
由于论坛开始,注册会员较少,且会员数是论坛敏感隐私数据,一般不要对外显示,因此需要删除注册会员数,步骤discuz根目录--》template--》default--》forum--》discuz.htm
Discuz!X3.2数据表参数说明查询表
Discuz! X3.2 数据pre_common_admincp_cmenu 后台 首页 | 常用操作管理数据表pre_common_admincp_group 后台 站长 | 团队职务数据表
Python实现Discuz论坛的自动POST登录发贴回帖实例
下面简单说下过程:首先是得到了login的post地址:几个关键的parameter是loginurl为登录面页,用于获得formhash的值loginsubmiturl为post登录参数的地址
LAMP+discuz安装论坛的方法
LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整台系统和相关软件,能够提供动态web站点服务及其应用开发环境LAMP是一个缩写词,具体包括Linux操作系统
相关源码
-
帝国cms7.5个人博客资讯文章模板下载本模板简洁个人博客网站设计开发,采用帝国CMS内核构建,只需替换文字图片即可快速搭建专业网站。自适应手机端设计,数据实时同步,操作简单便捷。PHP程序确保安全稳定运行,帮助您以较低成本获取持续业务。查看源码 -
(PC+WAP)玻璃钢不锈钢钢材环保设备pbootcms网站模板采用PbootCMS内核开发的响应式网站模板,为玻璃钢环保设备制造、不锈钢钢材贸易企业设计,适配产品展示及企业服务场景。通过自适应技术实现PC与WAP端数据实时同步查看源码 -
自适应APP应用程序介绍推广落地页pbootcms网站源码下载移动应用开发商设计的营销型落地页模板,基于PbootCMS内核深度开发采用前沿响应式架构,无缝适配手机端操作习惯与PC端展示需求。查看源码 -
(响应式)轴承机械五金零件产品pbootcms落地推广单页源码下载为轴承、机械零件等工业产品打造的响应式单页模板,基于PbootCMS内核开发,助力企业快速构建专业级产品展示页面。模板采用工业风设计语言,突出产品参数与性能优势,适用于设备制造商、零部件供应商等B2B场景推广。查看源码 -
WordPress个人博客主题 - wp-Concise-v1.0免费下载wp-Concise-v1.0是一款专为个人博客设计的简约风格主题,采用全宽排版设计理念,注重内容呈现效果。该模板适用于个人随笔、技术分享、生活记录等博客场景,帮助用户打造专业的内容展示空间。查看源码 -
(自适应)工业机械制造设备网站pbootcms模板下载为机械制造、工业设备类企业设计,特别适合各类机械设备、生产线、工业自动化产品展示。采用响应式技术,确保在不同设备上都能清晰展示机械产品的技术参数和细节特点。查看源码
| 分享笔记 (共有 篇笔记) |
