discuz緩存機制

1、 discuz緩存機制分析:php

使用緩存機制的目的很明顯,下降服務器性能的消耗,對於經常使用且變更比較小的數據的數據,能夠儘量的使用緩存來解決,代替最原生的不斷的進行數據庫查詢匹配的過程。而Discuz中提供的數據緩存方式包括內存、數據庫、文件三種方式,具體以下。java

(1)、項目根目錄/config/config_global.php配置數據庫/文件緩存方式,固然還有第三種,就是內存緩存。web

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

(2)、緩存數據獲取:redis

根目錄/source/function/function_core.php:sql

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(!@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 服務器支持方式,獲取到數據且不空則返回其結果;ruby

當服務器不支持內存緩存時,使用第二種文件緩存,文件緩存會將數據存放於目錄 ./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腳本生成緩存數據,緩存數據的存放根據系統設定好的緩存方式進行存儲。

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

2、 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)
相關文章
相關標籤/搜索