Redis、Memcached简单封装
2016-03-19 15:12
495 查看
很多项目中都会用到memcached、redis作缓存,一般我们获取数据都会优先从缓存获取数据,如果缓存中没有,再去读取数据库或者从其他方式获得相应的数据,处理之后返回同时种入缓存,那么很多时候代码便要重复这样一个判断逻辑,于是在这里,考虑了这么一种方式,简单地封装了一个缓存控制类,在从缓存读取数据的时候传入一个回调函数,如果缓存中不存在就执行回调函数,返回回调函数的结果,并自动将结果存入缓存。
首先定义缓存控制类的接口
memcached
redis,这里采用字符串或哈希的结构设置缓存
这样实现有一个好处就是能比较容易实现redis、memcached之间的自由切换,考虑用传入回调函数而不是sql语句的方式,一个是因为数据不一定来自数据库,或许来自其他公共的接口等,不是sql而是fsockopen、curl等等,这样能够保证更好的灵活性,其二是通过传sql返回的结果是没有经过相应处理的,适用的范围也相对受限制。
首先定义缓存控制类的接口
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返回的结果是没有经过相应处理的,适用的范围也相对受限制。
相关文章推荐
- memcache中的add和set方法区别
- memcached +mysql+php 测试例子
- php开发memcached
- memcache安装部署
- Memcache Brief Intro
- memcached php扩展(二)
- Memcached(3)-------Memcached的内存存储理解
- 基于Memcached的Session共享问题
- linux memcache 安装
- NoSQL -- memcache安装 加载php 共享session
- MemCache超详细解读
- memcached对nginx负载tomcat集群共享session
- mysql memcached 初探
- Memcache,Redis,MongoDB(数据缓存系统)方案对比与分析
- Memcache引入Repcached组件做HA高可用方案
- Linux上安装memcached
- memcache与redis lru 一致性hash 缓存雪崩 缓存无底洞 永久数据被踢现象
- Linux下memcache的安装和启动
- Redis与Memcached的区别
- memcached的安装与开启脚本