该文是wecenter学习笔记的一部分
Cache的实现原理
wecenter支持两种缓存
- Memcached
- File
基于Zend_Cache实现的文件缓存机制。
system/core/cache.php
$this->cache_factory = Zend_Cache::factory($this->frontendName, $this->backendName, $this->frontendOptions, $this->backendOptions);
读缓存
$result = $this->cache_factory->load($this->cachePrefix . $key);
写缓存
$result = $this->cache_factory->save($value, $this->cachePrefix . $key, array(), $lifetime);
删除缓存
return $this->cache_factory->remove($key);
清理缓存
return $this->cache_factory->clean(Zend_Cache::CLEANING_MODE_ALL);
Zend Cache
为了方便使用,Zend Cache根据缓存的数据类型构造了各种 FrontCache,并根据存储类型引入了BackendCache的概念。
** Frontend **
Capture
Capture能将php的start和flush之间的输出缓存起来,内部通过ob_start注册的output_callback来将php的缓冲内容存储到缓存中。
Zend/Cache/Frontend/Capture.php#start
ob_start(array($this, '_flush')); ob_implicit_flush(false);
通过调用
ob_flush
来刷新缓冲区Page
捕获输出的部分内容
Output
使用方式
// if it is a cache miss, output buffering is triggered if (! $cache->start('mypage')) { // output everything as usual echo 'Hello world! '; echo 'This is cached ('.time().') '; $cache->end(); // output buffering ends } echo 'This is never cached ('.time().').';
Class
通过重写__call,代理目标对象的函数调用,并将函数调用结果缓存起来。
public function __call($name, $parameters) { $callback = array($this->_cachedEntity, $name); if (!is_callable($callback, false)) { Zend_Cache::throwException('Invalid callback'); } $cacheBool1 = $this->_specificOptions['cache_by_default']; $cacheBool2 = in_array($name, $this->_specificOptions['cached_methods']); $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_methods']); $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3)); if (!$cache) { // We do not have not cache return call_user_func_array($callback, $parameters); } $id = $this->makeId($name, $parameters); if (($rs = $this->load($id)) && (array_key_exists(0, $rs)) && (array_key_exists(1, $rs)) ) { // A cache is available $output = $rs[0]; $return = $rs[1]; } else { // A cache is not available (or not valid for this frontend) ob_start(); ob_implicit_flush(false); try { $return = call_user_func_array($callback, $parameters); $output = ob_get_clean(); $data = array($output, $return); $this->save( $data, $id, $this->_tags, $this->_specificLifetime, $this->_priority ); } catch (Exception $e) { ob_end_clean(); throw $e; } } echo $output; return $return; }
Function
缓存函数调用的结果
function call($callback, array $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8)
调用这个函数,会跟进函数名称和参数生成缓存主键,如果缓存有效,则直接返回缓存结果,否则调用函数并进行缓存,与classs的__call实现基本一致。
File
根据文件的修改状态来判断缓存是否有效。
** Backend **
需要符合基本的接口
Zend/Cache/Backend/Interface.php
public function setDirectives($directives);
public function load($id, $doNotTestCacheValidity = false);
public function test($id);
public function save($data, $id, $tags = array(), $specificLifetime = false);
public function remove($id);
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array());
File
基于文件系统的缓存。
每个缓存除了生存缓存文件外,还会生出一个文件名以
internal-metadatas---
开头的元数据文件,并依靠元数据文件来存储数据的基本信息:Zend/Cache/Backend/File.php#touch
'hash' => $metadatas['hash'], 'mtime' => time(), 'expire' => $metadatas['expire'] + $extraLifetime, 'tags' => $metadatas['tags']
Sqlite
将数据和元数据存储到sqlite中
Zend/Cache/Backend/Sqlite.php#_buildStructure
private function _buildStructure() { $this->_query('DROP INDEX tag_id_index'); $this->_query('DROP INDEX tag_name_index'); $this->_query('DROP INDEX cache_id_expire_index'); $this->_query('DROP TABLE version'); $this->_query('DROP TABLE cache'); $this->_query('DROP TABLE tag'); $this->_query('CREATE TABLE version (num INTEGER PRIMARY KEY)'); $this->_query('CREATE TABLE cache (id TEXT PRIMARY KEY, content BLOB, lastModified INTEGER, expire INTEGER)'); $this->_query('CREATE TABLE tag (name TEXT, id TEXT)'); $this->_query('CREATE INDEX tag_id_index ON tag(id)'); $this->_query('CREATE INDEX tag_name_index ON tag(name)'); $this->_query('CREATE INDEX cache_id_expire_index ON cache(id, expire)'); $this->_query('INSERT INTO version (num) VALUES (1)'); }
顾名思义,cache存储缓存数据,tag存储标签, version存储缓存的版本号。
每次执行操作之前都会调用
_checkAndBuildStructure
检查是否需要构建表结构
memcached
依赖
Memcache
客户端来提供服务。libmemcached
依赖
Memcached
来提供服务xcache
来自于lightd团队的开源缓存服务器
Apc
BlackHole
Static
TwoLevels
WinCache
wincache仅支持NTS(非线程安全版本)的PHP
ZendServer Disk
ZendServer Share memeory
ZendPlatform
涉及的缓存服务太多,不能一一探究。