首页  >  文章  >  php教程  >  PHP支持组操作的Memcache类

PHP支持组操作的Memcache类

WBOY
WBOY原创
2016-06-13 10:44:12780浏览

Memcache是PHP开发中较常用到的缓存方法,在高并发的系统中是必不可少的组成部分。
在实际开发中,Memcache存在一个比较不尽人意的问题,就是Memcache不能支持对key进行的组操作。
 
组操作,也可以称为域操作,比如说某个文章系统,在前台部分使用Memcache缓存了列表页数据、文章详细页数据,两种数据的量都比较多。那么,当后台发布了一篇文章的时候,列表页就应该需要更新到最新的列表——可能涉及到许多个列表页。当然,对文章详细页来说,它是不需要更新的。
 
好的,这个时候我们就需要删除原有缓存,让程序可以自动更新列表页数据。但是使用Memcache的flush函数有个问题,就是它会清空全部的数据,包括列表页和文章页的数据,在大并发的条件下,全部缓存删除后重建缓存的时候,将会有非常高的负载产生。
 
另外,还会有情况就是有些你不愿意删除的缓存变量,也会丢失了,比如说程序的配置,数据库为了提速而存到缓存的表结构等。
 
所以我们需要一个支持组操作的缓存机制,我们就可以把列表页设置成一个组,文章页数据是另外一个组,程序配置又是另外一个组等等。当需要重建列表页的时候,只需要删除列表页这个组里面全部的数据,而不会影响到别的组的数据。
 
测试了几种方案,还是以下的方案最为理想和高速,我们先看代码,再说原理:
 
 
class MyCache
{
    private $mmc = null;
    private $group = null;
    private $version = 1;
    function __construct($group){
        if(!class_exists('mmcache')){
            $this->mmc = false;
            return;
        }
        $this->mmc = new memcache();
        $this->mmc->addServer('192.168.1.5', 11211);
        $this->mmc->addServer('192.168.1.6', 11211);
        $this->group = $group;
        $this->version = $this->mmc->get('version_'.$group);
    }
    function set($key, $var, $expire=3600){
        if(!$this->mmc)return;
        return $this->mmc->set($this->group.'_'.$this->version.'_'.$key, $var, $expire);
    }
    function get($key){
        if(!$this->mmc)return;
        return $this->mmc->get($this->group.'_'.$this->version.'_'.$key);
    }
    function incr($key, $value=1){
        if(!$this->mmc)return;
        return $this->mmc->increment($this->group.'_'.$this->version.'_'.$key, $value);
    }
    function decr($key, $value=1){
        if(!$this->mmc)return;
        return $this->mmc->decrement($this->group.'_'.$this->version.'_'.$key, $value);
    }
    function delete($key){
        if(!$this->mmc)return;
        return $this->mmc->delete($this->group.'_'.$this->version.'_'.$key);
    }
    function flush(){
        if(!$this->mmc)return;
        ++$this->version;
        $this->mmc->set('version_'.$this->group, $this->version);
    }
}
?>
 
上面的类比较完整,包括链接Memcache服务,设置和获取值,增减值,还有删除key和全删除(flush)。这里包括了常规的Memcache操作功能,和对全删除(flush)操作的扩展。
 
从代码可以看到,支持组的flush功能的实现,是通过version这个key来实现的,也就是每次存该组的变量的时候,变量的key都会加入version值,version值是一个数字(从1开始),当存和取key的时候,version值都会被使用到。
 
当开发者要flush当前组的数据的时候,flush操作只是简单地改变一些version的值(加一),那么,下次存取key的时候,将获取不到原来的值——因为version改变了,也就是取的key名称已经改变了。这样原有的值会被Memcache自动回收,不会出现任何的效率开销。而且程序上只是增加一个version的存和取,数据量极小,对系统效率基本没有任何影响。
 
通过以上的类,可以针对Memcache缓存进行组的操作,而这个PHP类,还可以继续扩展,如加入socket直接访问memcache的接口功能,这样PHP环境中就不需要安装memcache扩展类了,这样更有效避免flush的误操作了,而且在加入apc等缓存机制后,socket访问memcache接口也不会比扩展慢多少。
 
另外,MyCache类还有个附加的功能:当memcache服务失效的时候,MyCache类只是简单返回空值,而不会直接出错。
 
以下附带MyCache类的使用方法:
 
 
// 引入定义
include('MyCache.php');
 
// 实例化
$mc = new MyCache('abc'); // 要有域
 
// 设置值
$mc->set('word', 'hello world', 900);
 
// 取得值
echo $mc->get('word');
 
// 删除值
$mc->delete('word');
echo $mc->get('word');
 
$mc->set('counter', 1, 290000);
echo $mc->get('counter');
 
// 增加值
$mc->incr('counter');
$mc->incr('counter');
echo $mc->get('counter');Memcache是PHP开发中较常用到的缓存方法,在高并发的系统中是必不可少的组成部分。
在实际开发中,Memcache存在一个比较不尽人意的问题,就是Memcache不能支持对key进行的组操作。
 
组操作,也可以称为域操作,比如说某个文章系统,在前台部分使用Memcache缓存了列表页数据、文章详细页数据,两种数据的量都比较多。那么,当后台发布了一篇文章的时候,列表页就应该需要更新到最新的列表——可能涉及到许多个列表页。当然,对文章详细页来说,它是不需要更新的。
 
好的,这个时候我们就需要删除原有缓存,让程序可以自动更新列表页数据。但是使用Memcache的flush函数有个问题,就是它会清空全部的数据,包括列表页和文章页的数据,在大并发的条件下,全部缓存删除后重建缓存的时候,将会有非常高的负载产生。
 
另外,还会有情况就是有些你不愿意删除的缓存变量,也会丢失了,比如说程序的配置,数据库为了提速而存到缓存的表结构等。
 
所以我们需要一个支持组操作的缓存机制,我们就可以把列表页设置成一个组,文章页数据是另外一个组,程序配置又是另外一个组等等。当需要重建列表页的时候,只需要删除列表页这个组里面全部的数据,而不会影响到别的组的数据。
 
测试了几种方案,还是以下的方案最为理想和高速,我们先看代码,再说原理:
 
 
class MyCache
{
    private $mmc = null;
    private $group = null;
    private $version = 1;
    function __construct($group){
        if(!class_exists('mmcache')){
            $this->mmc = false;
            return;
        }
        $this->mmc = new memcache();
        $this->mmc->addServer('192.168.1.5', 11211);
        $this->mmc->addServer('192.168.1.6', 11211);
        $this->group = $group;
        $this->version = $this->mmc->get('version_'.$group);
    }
    function set($key, $var, $expire=3600){
        if(!$this->mmc)return;
        return $this->mmc->set($this->group.'_'.$this->version.'_'.$key, $var, $expire);
    }
    function get($key){
        if(!$this->mmc)return;
        return $this->mmc->get($this->group.'_'.$this->version.'_'.$key);
    }
    function incr($key, $value=1){
        if(!$this->mmc)return;
        return $this->mmc->increment($this->group.'_'.$this->version.'_'.$key, $value);
    }
    function decr($key, $value=1){
        if(!$this->mmc)return;
        return $this->mmc->decrement($this->group.'_'.$this->version.'_'.$key, $value);
    }
    function delete($key){
        if(!$this->mmc)return;
        return $this->mmc->delete($this->group.'_'.$this->version.'_'.$key);
    }
    function flush(){
        if(!$this->mmc)return;
        ++$this->version;
        $this->mmc->set('version_'.$this->group, $this->version);
    }
}
?>
 
上面的类比较完整,包括链接Memcache服务,设置和获取值,增减值,还有删除key和全删除(flush)。这里包括了常规的Memcache操作功能,和对全删除(flush)操作的扩展。
 
从代码可以看到,支持组的flush功能的实现,是通过version这个key来实现的,也就是每次存该组的变量的时候,变量的key都会加入version值,version值是一个数字(从1开始),当存和取key的时候,version值都会被使用到。
 
当开发者要flush当前组的数据的时候,flush操作只是简单地改变一些version的值(加一),那么,下次存取key的时候,将获取不到原来的值——因为version改变了,也就是取的key名称已经改变了。这样原有的值会被Memcache自动回收,不会出现任何的效率开销。而且程序上只是增加一个version的存和取,数据量极小,对系统效率基本没有任何影响。
 
通过以上的类,可以针对Memcache缓存进行组的操作,而这个PHP类,还可以继续扩展,如加入socket直接访问memcache的接口功能,这样PHP环境中就不需要安装memcache扩展类了,这样更有效避免flush的误操作了,而且在加入apc等缓存机制后,socket访问memcache接口也不会比扩展慢多少。
 
另外,MyCache类还有个附加的功能:当memcache服务失效的时候,MyCache类只是简单返回空值,而不会直接出错。
 
以下附带MyCache类的使用方法:
 
 
// 引入定义
include('MyCache.php');
 
// 实例化
$mc = new MyCache('abc'); // 要有域
 
// 设置值
$mc->set('word', 'hello world', 900);
 
// 取得值
echo $mc->get('word');
 
// 删除值
$mc->delete('word');
echo $mc->get('word');
 
$mc->set('counter', 1, 290000);
echo $mc->get('counter');
 
// 增加值
$mc->incr('counter');
$mc->incr('counter');
echo $mc->get('counter');
 
// 减少值
$mc->decr('counter');
echo $mc->get('counter');
 
// 按组删
$mc->flush(); 
本文出自 “振中的技术记事本” 博客
 
// 减少值
$mc->decr('counter');
echo $mc->get('counter');
 
// 按组删
$mc->flush(); 
作者“振中的技术记事本”

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn