Redis、Memcached简单封装

来源:互联网 发布:矩阵式项目管理 编辑:程序博客网 时间:2024/05/22 08:26

        很多项目中都会用到memcached、redis作缓存,一般我们获取数据都会优先从缓存获取数据,如果缓存中没有,再去读取数据库或者从其他方式获得相应的数据,处理之后返回同时种入缓存,那么很多时候代码便要重复这样一个判断逻辑,于是在这里,考虑了这么一种方式,简单地封装了一个缓存控制类,在从缓存读取数据的时候传入一个回调函数,如果缓存中不存在就执行回调函数,返回回调函数的结果,并自动将结果存入缓存。

        首先定义缓存控制类的接口

    interface Interface_Cache {                /**         * 获取当前缓存控制类实例,单例模式         */        public static function getInstance();                /**         * 获取当前类中原生mc、redis对象         */        public function query();                /**         * 读取配置设置缓存         * @param array $cache_config 缓存配置         * @param array $cache_params 缓存参数,构造key         * @param callable $func 回调函数,返回应当设置的值,返回值为null时,不设置缓存数据         */        public function set(array $cache_config, array $cache_params, callable $func);                /**         * 优先从缓存读取数据,如果缓存中不存在,执行回调函数获得数据返回,同时将数据写入缓存         * @param array $cache_config 缓存配置         * @param array $cache_params 缓存参数,构造key         * @param callable $func 回调函数,返回查询的数据,返回值为null时,不写入缓存         */        public function get(array $cache_config, array $cache_params, callable $func);            }
  然后进行不同的实现

  memcached

    class Base_Mc implements Interface_Cache {        private $_mc = null;        private static $_instance = null;                private function __construct() {            $this->_mc = new Memcached();            $this->_mc->addServer('127.0.0.1', 11211);        }                public static function getInstance() {            if(is_null(self::$_instance)) {                self::$_instance = new self();            }            return self::$_instance;        }               public function query() {            return $this->_mc;        }                public function set(array $cache_config, array $cache_params, callable $func) {            $key = self::buildKey($cache_params, $cache_config['key']);            $expire = $cache_config['expire'];                        $data = call_user_func($func);            if(is_null($data)) {                return false;            }            $expire += $expire == 0? 0: time();            return $this->_mc->set($key, $data, $expire);        }                public function get(array $cache_config, array $cache_params, callable $func) {            $key = self::buildKey($cache_params, $cache_config['key']);            $expire = $cache_config['expire'];                        $data = null;            if(false === ($data = $this->_mc->get($key))) {                $data = call_user_func($func);                if(is_null($data)) {                    return null;                }                $expire += $expire == 0? 0: time();                $this->_mc->set($key, $data, $expire);            }            return $data;        }                private static function buildKey(array $args, $format) {            $key = vsprintf($format, $args);            return $key;        }                public function __destruct() {            unset($this->_mc);        }    }
redis,这里采用字符串或哈希的结构设置缓存

    class Base_Redis implements Interface_Cache {        private $_redis = null;        private static $_instance = null;                private function __construct() {            if(is_null($this->_redis)) {                $this->_redis = new Redis();                $this->_redis->connect('127.0.0.1', '6379', 3);            }        }                public static function getInstance() {            if(is_null(self::$_instance)) {                self::$_instance = new self();            }            return self::$_instance;        }                public function query() {            return $this->_redis;        }                public function set(array $cache_config, array $cache_params, callable $func) {            $key = self::buildKey($cache_params, $cache_config['key']);            $expire = $cache_config['expire'];                        $type = null;            $data = call_user_func($func);            if(is_null($data)) {                return false;            }                        if(is_string($data) || is_numeric($data)) {                $this->_redis->setex($key, $expire, $data);            } else if(is_array($data)) {                $this->_redis->hMset($key, $data);                $this->_redis->expire($key, $expire);            }            return true;        }                        public function get(array $cache_config, array $cache_params, callable $func) {            $key = self::buildKey($cache_params, $cache_config['key']);            $expire = $cache_config['expire'];                        $data = null;            $type = $this->_redis->type($key);            $data = $type == Redis::REDIS_HASH? $this->_redis->hGetAll($key): $this->_redis->get($key);            if(false === $data || empty($data)) {                $data = call_user_func($func);                                if(is_null($data)) {                    return null;                }                                if(is_string($data) || is_numeric($data)) {                    $this->_redis->setex($key, $expire, $data);                } else if(is_array($data)) {                    $this->_redis->hMset($key, $data);                    $this->_redis->expire($key, $expire);                }            }            return $data;        }                private static function buildKey(array $args, $format) {            $key = vsprintf($format, $args);            $key = str_replace('_', ':', $key);            return $key;        }                           public function __destruct() {            $this->_redis->close();            unset($this->_redis);        }         }
示例代码

    class UserModel {                public static function getUserInfoById($user_id) {            $params = ['userId' => $user_id ];            $mc = Base_Mc::getInstance();            $cache_config = Comm_Config::get('cache.user');            $info = $mc->get($cache_config, $params, function() use ($params){                $user_sql = Impl_User::getInstance();                $rs = $user_sql->auto()->buildQuery($params)->exec();                if(empty($rs[0])) {                    return null;                }                return $rs[0][0];            });            return $info;        }    }

这样实现有一个好处就是能比较容易实现redis、memcached之间的自由切换,考虑用传入回调函数而不是sql语句的方式,一个是因为数据不一定来自数据库,或许来自其他公共的接口等,不是sql而是fsockopen、curl等等,这样能够保证更好的灵活性,其二是通过传sql返回的结果是没有经过相应处理的,适用的范围也相对受限制。


0 1
原创粉丝点击