PHP 缓存实现代码及详细注释

复制代码 代码如下:
class CacheException extends Exception {}
/**
* 缓存抽象类
*/
abstract class Cache_Abstract {
/**
* 读缓存变量
*
* @param string $key 缓存下标
* @return mixed
*/
abstract public function fetch($key);

数码缓存:这里所说的数目缓存是指数据库查询PHP缓存机制,每趟访谈页面包车型地铁时候,都会先检查评定相应的缓存数据是还是不是留存,假诺海市蜃楼,就接连数据库,拿到数码,并把询问结果体系化后保存到文件中,未来相近的查询结果就间接从缓存表或文件中获得。

/**
* 缓存变量
*
* @param string $key 缓存变量下标
* @param string $value 缓存变量的值
* @return bool
*/
abstract public function store($key, $value);

用的最广的例证看Discuz的搜索效果,把结果ID缓存到三个表中,后一次找寻相通关键字时先找找缓存表。

/**
* 删除缓存变量
*
* @param string $key 缓存下标
* @return Cache_Abstract
*/
abstract public function delete($key);

举个常用的法子,多表关联的时候,把附表中的内容生成数组保存到主表的叁个字段中,须求的时候数组分解一下,那样的收益是只读一个表,坏处就是多少个数据同步会多不菲步骤,数据库永恒是瓶颈,用硬盘换速度,是这些的关键点。

/**
* 清(删卡塔尔(قطر‎除具有缓存
*
* @return Cache_Abstract
*/
abstract public function clear();

页面缓存:

/**
* 锁定缓存变量
*
* @param string $key 缓存下标
* @return Cache_Abstract
*/
abstract public function lock($key);
/**
* 缓存变量解锁
*
* @param string $key 缓存下标
* @return Cache_Abstract
*/
abstract public function unlock($key);
/**
* 获得缓存变量是还是不是被锁定
*
* @param string $key 缓存下标
* @return bool
*/
abstract public function isLocked($key);
/**
* 确定保证不是锁定状态
* 最多做$tries次睡眠等待解锁,超时则跳过并解锁
*
* @param string $key 缓存下标
*/
public function checkLock($key) {
if (!$this->isLocked($key)) {
return $this;
}

历次访谈页面包车型大巴时候,都会先检测相应的缓存页面文件是不是存在,如果不设有,就总是数据库,拿到数码,呈现页面并同临时间生成缓存页面文件,那样后一次作客的时候页面文件就发挥效用了。(模板引擎和英特网广泛的有的PHP缓存机制类平常常有此作用卡塔尔

$tries = 10;
$count = 0;
do {
usleep(200);
$count ++;
} while ($count <= $tries && $this->is洛克d($key卡塔尔(قطر‎卡塔尔(قطر‎; //
最多做11回睡眠等待解锁,超时则跳过并解锁
$this->isLocked($key) && $this->unlock($key);

光阴接触缓存:

return $this;
}
}

反省文件是或不是留存並且时间戳小于设置的过期时间,即使文件更正的小时戳比当前光阴戳减去过期时间戳大,那么就用缓存,不然更新缓存。

/**
* APC增加缓存实现
*
*
* @category Mjie
* @package Cache
* @author 流水青阳
* @copyright Copyright (c) 2008-
* @license New BSD License
* @version $Id: Cache/Apc.php 版本号 2010-04-18 23:02 cmpan $
*/
class Cache_Apc extends Cache_Abstract {

剧情触发缓存:

protected $_prefix = ‘cache.mjie.net’;

当插入数据或更新数据时,免强更新PHP缓存机制。

public function __construct() {
if (!function_exists(‘apc_cache_info’)) {
throw new CacheException(‘apc extension didn’t installed’);
}
}

静态缓存:

/**
* 保存缓存变量
*
* @param string $key
* @param mixed $value
* @return bool
*/
public function store($key, $value) {
return apc_store($this->_storageKey($key), $value);
}

此处所说的静态缓存是指静态化,间接生成HTML或XML等文件文件,有立异的时候重生成一回,切合于不太变化的页面,那就掩盖了。

/**
* 读取缓存
*
* @param string $key
* @return mixed
*/
public function fetch($key) {
return apc_fetch($this->_storageKey($key));
}

上述内容是代码级的减轻方案,作者直接CP别的框架,也懒得改,内容都大致,非常轻易就完结,何况会两种办法豆蔻梢头并用,但上面包车型地铁原委是劳务器端的缓存方案,非代码级的,要有多方面包车型大巴搭档技能成功

/**
* 肃清缓存
*
* @return Cache_Apc
*/
public function clear() {
apc_clear_cache();
return $this;
}

内部存款和储蓄器缓存:

/**
* 删除缓存单元
*
* @return Cache_Apc
*/
public function delete($key) {
apc_delete($this->_storageKey($key));
return $this;
}

Memcached是高质量的,分布式的内部存款和储蓄器对象PHP缓存机制系统,用于在动态应用中收缩数据库负载,进步访谈速度。

/**
* 缓存单元是还是不是被锁定
*
* @param string $key
* @return bool
*/
public function isLocked($key) {
if ((apc_fetch($this->_storageKey($key) . ‘.lock’)) === false) {
return false;
}

php的缓冲器:

return true;
}

有eaccelerator, apc,
phpa,xcache,这么些这几个就不说了吧,寻找一群一堆的,本身看呀,知道有这东西就OK

/**
* 锁定缓存单元
*
* @param string $key
* @return Cache_Apc
*/
public function lock($key) {
apc_store($this->_storageKey($key) . ‘.lock’, ”, 5);
return $this;
}

MYSQL缓存:

/**
* 缓存单元解锁
*
* @param string $key
* @return Cache_Apc
*/
public function unlock($key) {
apc_delete($this->_storageKey($key) . ‘.lock’);
return $this;
}

那也算非代码级的,杰出的数据库正是用的这种格局,看上边的运营时刻,0.09xxx之类的
自家贴段依据羊毛白这东西改良后局部my.ini吧,2G的MYISAM表可以在0.05S左右,据他们说她上下改了有快一年

/**
* 完整缓存名
*
* @param string $key
* @return string
*/
private function _storageKey($key) {
return $this->_prefix . ‘_’ . $key;
}
}
/**
* 文件缓存完毕
*
*
* @category Mjie
* @package Cache
* @author 流水春王
* @copyright Copyright (c) 2008-
* @license New BSD License
* @version $Id: Cache/File.php 版本号 2010-04-18 16:46 cmpan $
*/
class Cache_File extends Cache_Abstract {

听别人讲反向代理的Web缓存:

protected $_cachesDir = ‘cache’;

如Nginx,SQUID,mod_proxy(apache2以上又分为mod_proxy和mod_cache)
NGINX的例子

public function __construct() {
if (defined(‘DATA_DIR’)) {
$this->_setCacheDir(DATA_DIR . ‘/cache’);
}
}

用google找到一些 php缓存技能形式

/**
* 获取缓存文件
*
* @param string $key
* @return string
*/
protected function _getCacheFile($key) {
return $this->_cachesDir . ‘/’ . substr($key, 0, 2) . ‘/’ . $key .
‘.php’;
}
/**
* 读取缓存变量
* 为防备音讯走漏,缓存文件格式为php文件,并以”

发个PHP缓存达成,完毕了apc和文件缓存,世襲Cache_Abstract就能够兑现调用第三方的缓存工具。
仿效shindig的缓存类和apc。

“开头
*
* @param string $key 缓存下标
* @return mixed
*/
public function fetch($key) {
$cacheFile = self::_getCacheFile($key);
if (file_exists($cacheFile) && is_readable($cacheFile)) {
return unserialize(@file_get_contents($cacheFile, false, NULL, 13));
}
return false;
}
/**
* 缓存变量
* 为防止音讯败露,缓存文件格式为php文件,并以”

Php代码

“开头
*
* @param string $key 缓存变量下标
* @param string $value 缓存变量的值
* @return bool
*澳门新葡萄京官网注册,/
public function store($key, $value) {
$cacheFile = self::_getCacheFile($key);
$cacheDir = dirname($cacheFile);
if(!is_dir($cacheDir)) {
if(mkdir($cacheDir” target=”_blank”>!@mkdir($cacheDir, 0755, true))
{
throw new CacheException(“Could not make cache directory”);
}
}
return @file_put_contents($cacheFile, ‘

 代码如下

‘ . serialize($value));
}
/**
* 删除缓存变量
*
* @param string $key 缓存下标
* @return Cache_File
*/
public function delete($key) {
if(emptyempty($key)) {
throw new CacheException(“Missing argument 1 for
Cache_File::delete()”);
}

<?php  
class CacheException extends Exception {}  
/** 
 * 缓存抽象类 
 */  
abstract class Cache_Abstract {  
    /** 
     * 读缓存变量 
     * 
     * @param string $key 缓存下标 
     * @return mixed 
     */  
    abstract public function fetch($key);  
      
    /** 
     * 缓存变量 
     * 
     * @param string $key 缓存变量下标 
     * @param string $value 缓存变量的值 
     * @return bool 
     */  
    abstract public function store($key, $value);  
      
    /** 
     * 删除缓存变量 
     * 
     * @param string $key 缓存下标 
     * @return Cache_Abstract 
     */  
    abstract public function delete($key);  
      
    /** 
     * 清(删卡塔尔(قطر‎除具备缓存 
     * 
     * @return Cache_Abstract 
     */  
    abstract public function clear();  
      
    /** 
     * 锁定缓存变量 
     * 
     * @param string $key 缓存下标 
     * @return Cache_Abstract 
     */  
    abstract public function lock($key);  
  
    /** 
     * 缓存变量解锁 
     * 
     * @param string $key 缓存下标 
     * @return Cache_Abstract 
     */  
    abstract public function unlock($key);  
  
    /** 
     * 拿到缓存变量是不是被锁定 
     * 
     * @param string $key 缓存下标 
     * @return bool 
     */  
    abstract public function isLocked($key);  
  
    /** 
     * 确定保障不是锁定状态 
     * 最多做$tries次睡眠等待解锁,超时则跳过并解锁 
     * 
     * @param string $key 缓存下标 
     */  
    public function checkLock($key) {  
        if (!$this->isLocked($key)) {  
            return $this;  
        }  
          
        $tries = 10;  
        $count = 0;  
        do {  
            usleep(200);  
            $count ++;  
        } while ($count <= $tries && $this->isLocked($key卡塔尔(قطر‎卡塔尔国;  //
最多做十四次睡眠等待解锁,超时则跳过并解锁  
  
        $this->isLocked($key) && $this->unlock($key);  
          
        return $this;  
    }  
}  
  
  
/** 
 * APC扩充缓存落成 
 *  
 *  
 * @category   Mjie 
 * @package    Cache 
 * @author     流水孟陬 
 * @copyright  Copyright (c) 2008- <cmpan(at)qq.com> 
 * @license    New BSD License 
 * @version    $Id: Cache/Apc.php 版本号 2010-04-18 23:02 cmpan $ 
 */  
class Cache_Apc extends Cache_Abstract {  
      
    protected $_prefix = ‘cache.mjie.net’;  
      
    public function __construct() {  
        if (!function_exists(‘apc_cache_info’)) {  
            throw new CacheException(‘apc extension didn’t
installed’);  
        }  
    }  
      
    /** 
     * 保存缓存变量 
     * 
     * @param string $key 
     * @param mixed $value 
     * @return bool 
     */  
    public function store($key, $value) {  
        return apc_store($this->_storageKey($key), $value);  
    }  
      
    /** 
     * 读取缓存 
     * 
     * @param string $key 
     * @return mixed 
     */  
    public function fetch($key) {  
        return apc_fetch($this->_storageKey($key));  
    }  
      
    /** 
     * 息灭缓存 
     * 
     * @return Cache_Apc 
     */  
    public function clear() {  
        apc_clear_cache();  
        return $this;  
    }  
      
    /** 
     * 删除缓存单元 
     * 
     * @return Cache_Apc 
     */  
    public function delete($key) {  
        apc_delete($this->_storageKey($key));  
        return $this;  
    }  
      
    /** 
     * 缓存单元是不是被锁定 
     * 
     * @param string $key 
     * @return bool 
     */  
    public function isLocked($key) {  
        if ((apc_fetch($this->_storageKey($key) . ‘.lock’)) ===
false) {  
            return false;  
        }  
          
        return true;  
    }  
      
    /** 
     * 锁定缓存单元 
     * 
     * @param string $key 
     * @return Cache_Apc 
     */  
    public function lock($key) {  
        apc_store($this->_storageKey($key) . ‘.lock’, ”, 5);  
        return $this;  
    }  
      
    /** 
     * 缓存单元解锁 
     * 
     * @param string $key 
     * @return Cache_Apc 
     */  
    public function unlock($key) {  
        apc_delete($this->_storageKey($key) . ‘.lock’);  
        return $this;  
    }  
      
    /** 
     * 完整缓存名 
     * 
     * @param string $key 
     * @return string 
     */  
    private function _storageKey($key) {  
        return $this->_prefix . ‘_’ . $key;  
    }  
}  
  
/** 
 * 文件缓存完成 
 *  
 *  
 * @category   Mjie 
 * @package    Cache 
 * @author     流水一月 
 * @copyright  Copyright (c) 2008- <cmpan(at)qq.com> 
 * @license    New BSD License 
 * @version    $Id: Cache/File.php 版本号 2010-04-18 16:46 cmpan $ 
 */  
class Cache_File extends Cache_Abstract {  
    public $useSubdir     = false;  
      
    protected $_cachesDir = ‘cache’;  
      
    public function __construct() {  
        if (defined(‘DATA_DIR’)) {  
            $this->_setCacheDir(DATA_DIR . ‘/cache’);  
        }  
    }  
      
    /** 
     * 获取缓存文件 
     * 
     * @param string $key 
     * @return string 
     */  
    protected function _getCacheFile($key) {  
        $subdir = $this->useSubdir ? substr($key, 0, 2) . ‘/’ :
”;  
        return $this->_cachesDir . ‘/’ . $subdir . $key .
‘.php’;  
    }  
  
    /** 
     * 读取缓存变量 
     * 为防止音讯走漏,缓存文件格式为php文件,并以”<?php
exit;?>”开头 
     *  
     * @param string $key 缓存下标 
     * @return mixed 
     */  
    public function fetch($key) {  
        $cacheFile = self::_getCacheFile($key);  
        if (file_exists($cacheFile) && is_readable($cacheFile)) {  
            // include 方式  
            //return include $cacheFile;  
            // 类别化情势  
  
            return unserialize(@file_get_contents($cacheFile, false,
NULL, 13));  
        }  
  
        return false;  
    }  
  
    /** 
     * 缓存变量 
     * 为防止音信外泄,缓存文件格式为php文件,并以”<?php
exit;?>”起头 
     * 
     * @param string $key 缓存变量下标 
     * @param string $value 缓存变量的值 
     * @return bool 
     */  
    public function store($key, $value) {  
        $cacheFile = self::_getCacheFile($key);  
        $cacheDir  = dirname($cacheFile);  
  
        if(!is_dir($cacheDir)) {  
            if(!@mkdir($cacheDir, 0755, true)) {  
                throw new CacheException(“Could not make cache
directory”);  
            }  
        }  
    // 用include方式  
        //return @file_put_contents($cacheFile, ‘<?php return ‘ .
var_export($value, true). ‘;’);  
  
        return @file_put_contents($cacheFile, ‘<?php exit;?>’ .
serialize($value));  
    }  
  
    /** 
     * 删除缓存变量 
     * 
     * @param string $key 缓存下标 
     * @return Cache_File 
     */  
    public function delete($key) {  
        if(emptyempty($key)) {  
            throw new CacheException(“Missing argument 1 for
Cache_File::delete()”);  
        }  
          
        $cacheFile = self::_getCacheFile($key);  
        if(!@unlink($cacheFile)) {  
            throw new CacheException(“Cache file could not be
deleted”);  
        }  
  
        return $this;  
    }  
  
    /** 
     * 缓存单元是或不是曾经锁定 
     * 
     * @param string $key 
     * @return bool 
     */  
    public function isLocked($key) {  
        $cacheFile = self::_getCacheFile($key);  
        clearstatcache();  
        return file_exists($cacheFile . ‘.lock’);  
    }  
  
    /** 
     * 锁定 
     * 
     * @param string $key 
     * @return Cache_File 
     */  
    public function lock($key) {  
        $cacheFile = self::_getCacheFile($key);  
        $cacheDir  = dirname($cacheFile);  
        if(!is_dir($cacheDir)) {  
            if(!@mkdir($cacheDir, 0755, true)) {  
                if(!is_dir($cacheDir)) {  
                    throw new CacheException(“Could not make cache
directory”);  
                }  
            }  
        }  
  
        // 设定缓存锁文件的拜见和改进时间  
        @touch($cacheFile . ‘.lock’);  
        return $this;  
    }  
    
    /** 
     * 解锁 
     * 
     * @param string $key 
     * @return Cache_File 
     */  
    public function unlock($key) {  
        $cacheFile = self::_getCacheFile($key);  
        @unlink($cacheFile . ‘.lock’);  
        return 

$cacheFile = self::_getCacheFile($key);
if($cacheFile” target=”_blank”>!@unlink($cacheFile)) {
throw new CacheException(“Cache file could not be deleted”);
}
return $this;
}
/**
* 缓存单元是还是不是业已锁定
*
* @param string $key
* @return bool
*/
public function isLocked($key) {
$cacheFile = self::_getCacheFile($key);
clearstatcache();
return file_exists($cacheFile . ‘.lock’);
}
/**
* 锁定
*
* @param string $key
* @return Cache_File
*/
public function lock($key) {
$cacheFile = self::_getCacheFile($key);
$cacheDir = dirname($cacheFile);
if(!is_dir($cacheDir)) {
if(mkdir($cacheDir” target=”_blank”>!@mkdir($cacheDir, 0755, true))
{
if(!is_dir($cacheDir)) {
throw new CacheException(“Could not make cache directory”);
}
}
}
// 设定缓存锁文件的拜望和改造时间
@touch($cacheFile . ‘.lock’);
return $this;
}

/**
* 解锁
*
* @param string $key
* @return Cache_File
*/
public function unlock($key) {
$cacheFile = self::_getCacheFile($key);
@unlink($cacheFile . ‘.lock’);
return $this;
}
/**
* 设置文件缓存目录
* @param string $dir
* @return Cache_File
*/
protected function _setCacheDir($dir) {
$this->_cachesDir = rtrim(str_replace(‘\’, ‘/’, trim($dir)),
‘/’);
clearstatcache();
if(!is_dir($this->_cachesDir)) {
mkdir($this->_cachesDir, 0755, true);
}
//
return $this;
}

/**
* 清空全体缓存
*
* @return Cache_File
*/
public function clear() {
// 遍历目录肃清缓存
$cacheDir = $this->_cachesDir;
$d = dir($cacheDir);
while(false !== ($entry = $d->read())) {
if(‘.’ == $entry[0]) {
continue;
}

$cacheEntry = $cacheDir . ‘/’ . $entry;
if(is_file($cacheEntry)) {
@unlink($cacheEntry);
} elseif(is_dir($cacheEntry)) {
// 缓存文件夹有两级
$d2 = dir($cacheEntry);
while(false !== ($entry = $d2->read())) {
if(‘.’ == $entry[0]) {
continue;
}

$cacheEntry .= ‘/’ . $entry;
if(is_file($cacheEntry)) {
@unlink($cacheEntry);
}
}
$d2->close();
}
}
$d->close();

return $this;
}
}
/**
* 缓存单元的数据结构
* array(
* ‘time’ => time(State of Qatar, // 缓存写入时的年月戳
* ‘expire’ => $expire, // 缓存过期时刻
* ‘valid’ => true, // 缓存是还是不是管用
* ‘data’ => $value // 缓存的值
* );
*/
final class Cache {
/**
* 缓存过期日子长度(sState of Qatar
*
* @var int
*/
private $_expire = 3600;
/**
* 缓存管理类
*
* @var Cache_Abstract
*/
private $_storage = null;
/**
* @return Cache
*/
static public function createCache($cacheClass = ‘Cache_File’) {
return new self($cacheClass);
}
private function __construct($cacheClass) {
$this->_storage = new $cacheClass();
}
/**
* 设置缓存
*
* @param string $key
* @param mixed $value
* @param int $expire
*/
public function set($key, $value, $expire = false) {
if (!$expire) {
$expire = $this->_expire;
}

$this->_storage->checkLock($key);

$data = array(‘time’ => time(), ‘expire’ => $expire, ‘valid’ =>
true, ‘data’ => $value);
$this->_storage->lock($key);

try {
$this->_storage->store($key, $data);
$this->_storage->unlock($key);
} catch (CacheException $e) {
$this->_storage->unlock($key);
throw $e;
}
}
/**
* 读取缓存
*
* @param string $key
* @return mixed
*/
public function get($key) {
$data = $this->fetch($key);
if ($data && $data[‘valid’] && !$data[‘isExpired’]) {
return $data[‘data’];
}

return false;
}
/**
* 读缓存,包括过期的和低效的,得到完整的储备布局
*
* @param string $key
*/
public function fetch($key) {
$this->_storage->checkLock($key);
$data = $this->_storage->fetch($key);
if ($data) {
$data[‘isExpired’] = (time() – $data[‘time’]) > $data[‘expire’]
? true : false;
return $data;
}

return false;
}
/**
* 删除缓存
*
* @param string $key
*/
public function delete($key) {
$this->_storage->checkLock($key)
->lock($key)
->delete($key)
->unlock($key);
}

public function clear() {
$this->_storage->clear();
}
/**
* 把缓存设为无效
*
* @param string $key
*/
public function setInvalidate($key) {
$this->_storage->checkLock($key)
->lock($key);
try {
$data = $this->_storage->fetch($key);
if ($data) {
$data[‘valid’] = false;
$this->_storage->store($key, $data);
}
$this->_storage->unlock($key);
} catch (CacheException $e) {
$this->_storage->unlock($key);
throw $e;
}
}

/**
* 设置缓存过期岁月(s)
*
* @param int $expire
*/
public function setExpire($expire) {
$this->_expire = (int) $expire;
return $this;
}
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注