6
回答
关于discuzX的缓存代码有点不明白的地方,请教大家

 

class discuz_memory
{
	var $config;
	var $extension = array();
	var $memory;
	var $prefix;
	var $type;
	var $keys;
	var $enable = false;
    //构造函数,检查eaccelerator,xcach,memcache是否存在
	function discuz_memory() {
		$this->extension['eaccelerator'] = function_exists('eaccelerator_get');
		$this->extension['xcache'] = function_exists('xcache_get');
		$this->extension['memcache'] = extension_loaded('memcache');
	}

	function init($config) {
         //内存存储配置
		$this->config = $config;
		//键值前缀
		$this->prefix = empty($config['prefix']) ? substr(md5($_SERVER['HTTP_HOST']), 0, 6).'_' : $config['prefix'];
		$this->keys = array();
        //memcache存储
		if($this->extension['memcache'] && !empty($config['memcache']['server'])) {
			require_once libfile('class/memcache');
			$this->memory = new discuz_memcache();
			$this->memory->init($this->config['memcache']);
			if(!$this->memory->enable) {
				$this->memory = null;
			}
		}
        //如果memcache联接失败,用eaccelerator
		if(!is_object($this->memory) && $this->extension['eaccelerator'] && $this->config['eaccelerator']) {
			require_once libfile('class/eaccelerator');
			$this->memory = new discuz_eaccelerator();
			$this->memory->init(null);
		}
        //使用xcache
		if(!is_object($this->memory) && $this->extension['xcache'] && $this->config['xcache']) {
			require_once libfile('class/xcache');
			$this->memory = new discuz_xcache();
			$this->memory->init(null);
		}
        //确定缓存对象
		if(is_object($this->memory)) {
			$this->enable = true;
			//缓存类型
			$this->type = str_replace('discuz_', '', get_class($this->memory));
			$this->keys = $this->get('memory_system_keys');
			//是否存在memory_system_keys己经存在的key,没有则初始化
			$this->keys = !is_array($this->keys) ? array() : $this->keys;
		}

	}

	function get($key) {
		$ret = null;
		if($this->enable && (isset($this->keys[$key]) || $key == 'memory_system_keys')) {
			$ret = $this->memory->get($this->_key($key));
			if(!is_array($ret)) {
				$ret = null;
			} else {
				return $ret[0];
			}
		}
		return $ret;
	}

	function set($key, $value, $ttl = 0) {

		$ret = null;
		if($this->enable) {
			$ret = $this->memory->set($this->_key($key), array($value), $ttl);
			if($ret) {
				//这个地方不明白?为什么要把所有的Key存入到$this->keys中呢?还要存入到memory_system_keys,//这样不担心存入的key特别的多(如有一百万个缓存),每次请求的时候不担心占用大量的内存???
				$this->keys[$key] = true;
				$this->memory->set($this->_key('memory_system_keys'), array($this->keys));
			}
		}
		return $ret;
	}

	function rm($key) {
		$ret = null;
		if($this->enable) {
			$ret = $this->memory->rm($this->_key($key));
			if($ret) {
				unset($this->keys[$key]);
				$this->memory->set($this->_key('memory_system_keys'), array($this->keys));
			}
		}
		return $ret;
	}

	function clear() {
		if($this->enable && is_array($this->keys)) {
			$this->keys['memory_system_keys'] = true;
			foreach ($this->keys as $k => $v) {
				$this->memory->rm($this->_key($k));
			}
		}
		$this->keys = array();
		return true;
	}

	function _key($str) {
		return ($this->prefix).$str;
	}

}

 

举报
yanyongshan
发帖于8年前 6回/1K+阅
共有6个答案 最后回答: 8年前

  1.  if($ret) {  
  2.                 //这个地方不明白?为什么要把所有的Key存入到$this->keys中呢?还要存入到memory_system_keys,//这样不担心存入的key特别的多(如有一百万个缓存),每次请求的时候不担心占用大量的内存???  
  3.                 $this->keys[$key] = true;  
  4.                 $this->memory->set($this->_key('memory_system_keys'), array($this->keys));  
  5.             }  

首先要要明确两点知识:

1、PHP类的知识,它是实例化,全局使用,不做第二次实例(在discuz里),$this->keys[$key] = true;   在全局里就可以判断某个key已经缓存,如果在某个地方做了缓存,再到其它位置(php同一个进行时的不同位置)要做同样的事情,就可以知道某个$this->keys[$key] 已存在(当然会检查是否有效,过期),不需要再调用缓存set(),而直接可以返回缓存。

2、php缓存的原理,无非就是第一次检查是否存在key的缓存,如果没有就设置key=>value,其它不同的请求,就检查同用的key(在有效期内)是否存在,就调用,不用再做获存数据这个复杂耗时的过程,起到加速的作用。(当然缓存中间件会有如下的设定:过期,总缓存的总容量这些重要的设定参数,如超过容量合子,新设定的缓存会把旧的缓存挤出缓存合子)。

实现代码一般是这样:

$cache_obj  = 'some cahce object';

if(!$data = $cache_obj->get(‘news_threads’)){

//做了好复杂的数据查询,处理,过滤,整理等工作,非常耗时的过程,得到data这个大型的数据

$data = $value //may be array(');

$cache_obj->set('news_threads', $data);

}

//以下是对$data这个数据进行使用,输出

var_dump($data)

.......

//又有一个地方,在同一个php文件里,可能要用到news_threads这个缓存key,

可以直接这样判断$cache_obj->isset(''news_threads);

引用来自#4楼“杨金焕”的帖子

首先要要明确两点知识:

1、PHP类的知识,它是实例化,全局使用,不做第二次实例(在discuz里),$this->keys[$key] = true;   在全局里就可以判断某个key已经缓存,如果在某个地方做了缓存,再到其它位置(php同一个进行时的不同位置)要做同样的事情,就可以知道某个$this->keys[$key] 已存在(当然会检查是否有效,过期),不需要再调用缓存set(),而直接可以返回缓存。

2、php缓存的原理,无非就是第一次检查是否存在key的缓存,如果没有就设置key=>value,其它不同的请求,就检查同用的key(在有效期内)是否存在,就调用,不用再做获存数据这个复杂耗时的过程,起到加速的作用。(当然缓存中间件会有如下的设定:过期,总缓存的总容量这些重要的设定参数,如超过容量合子,新设定的缓存会把旧的缓存挤出缓存合子)。

实现代码一般是这样:

$cache_obj  = 'some cahce object';

if(!$data = $cache_obj->get(‘news_threads’)){

//做了好复杂的数据查询,处理,过滤,整理等工作,非常耗时的过程,得到data这个大型的数据

$data = $value //may be array(');

$cache_obj->set('news_threads', $data);

}

//以下是对$data这个数据进行使用,输出

var_dump($data)

.......

//又有一个地方,在同一个php文件里,可能要用到news_threads这个缓存key,

可以直接这样判断$cache_obj->isset(''news_threads);

1.你说的discuz的全局对象我知道是全局的,但是当我打开一个新的页面的时候,不还是需要再实例化一次??

2.$data你也说过了,是一个超大的数据,为什么需要保存这么多的key呢??如果不保存这么多的key,无非就是到memcache去根据这个key读取是否有值,如果没有值,就去数据库取,不就可以了吗??何苦要保存所有的key呢?

  1. $this->keys[$key] = true;   
  2. $this->memory->set($this->_key('memory_system_keys'), array($this->keys));   

在同一个php运行进程里,有可能多个缓存,在每处设定缓存时,可以根据$this->keys[$key]来判断是否存在。

而助key可能不会太多,它只是一个变量的别名,不是变量的值。

顶部