[关闭]
@a5635268 2017-05-12T14:33:01.000000Z 字数 5151 阅读 1199

【redis专题(14)】在PHP中使用redis(2)

Redis


我们在使用PHPredis扩展来操作PHP时,不会直接new redis();,一般要重新封装一下,才进行使用。

封装什么?怎么封装? 为什么要封装?

  1. 使用适配器模式,便于后期缓存中间件的替换,比如某日从redis替换为memcache。
  2. 使用单列模式,使内存中只有一个缓存实例。
  3. 缓存KEY要统一配置,便于后期批量更改和管理。

缓存适配器 (Thinkphp)

  1. namespace Think;
  2. /**
  3. * 缓存管理类
  4. */
  5. class Cache{
  6. /**
  7. * 操作句柄
  8. * @var string
  9. * @access protected
  10. */
  11. protected $handler;
  12. /**
  13. * 缓存连接参数
  14. * @var integer
  15. * @access protected
  16. */
  17. protected $options = [];
  18. /**
  19. * 连接缓存
  20. * @access public
  21. * @param string $type 缓存类型
  22. * @param array $options 配置数组
  23. * @return object
  24. */
  25. public function connect($type = '' , $options = []){
  26. if (empty($type))
  27. $type = C('DATA_CACHE_TYPE');
  28. $class = strpos($type , '\\') ? $type : 'Think\\Cache\\Driver\\' . ucwords(strtolower($type));
  29. if (class_exists($class))
  30. $cache = new $class($options); else
  31. E(L('_CACHE_TYPE_INVALID_') . ':' . $type); //错误输出
  32. return $cache;
  33. }
  34. /**
  35. * 取得缓存类实例
  36. * @static
  37. * @access public
  38. * @return mixed
  39. */
  40. static function getInstance($type = '' , $options = []){
  41. static $_instance = [];
  42. $guid = $type . to_guid_string($options); //全局唯一key生成,实现单列;
  43. if (!isset($_instance[$guid])) {
  44. $obj = new Cache();
  45. $_instance[$guid] = $obj->connect($type , $options);
  46. }
  47. return $_instance[$guid];
  48. }
  49. // 魔术方法,调用缓存中间件中类的get方法获取缓存值,即$cache->name;
  50. public function __get($name){
  51. return $this->get($name);
  52. }
  53. // 魔术方法,调用缓存中间件中类的set方法设置缓存值,即$cache->name = $value;
  54. public function __set($name , $value){
  55. return $this->set($name , $value);
  56. }
  57. // unset($cache->name); 就删掉了该缓存;
  58. public function __unset($name){
  59. $this->rm($name);
  60. }
  61. //调用缓存类型自己的方法
  62. public function __call($method , $args){
  63. if (method_exists($this->handler , $method)) {
  64. return call_user_func_array([$this->handler , $method] , $args);
  65. } else {
  66. E(__CLASS__ . ':' . $method . L('_METHOD_NOT_EXIST_'));
  67. return;
  68. }
  69. }
  70. public function setOptions($name , $value){
  71. $this->options[$name] = $value;
  72. }
  73. public function getOptions($name){
  74. return $this->options[$name];
  75. }
  76. /**
  77. * 队列缓存,设置和获取队列key的值
  78. * @access protected
  79. * @param string $key 队列名
  80. * @return mixed
  81. */
  82. protected function queue($key){
  83. static $_handler = [
  84. // 获取与设置key到队列,三种驱动方法;
  85. 'file' => ['F' , 'F'] ,
  86. 'xcache' => ['xcache_get' , 'xcache_set'] ,
  87. 'apc' => ['apc_fetch' , 'apc_store'] ,
  88. ];
  89. $queue = isset($this->options['queue']) ? $this->options['queue'] : 'file';
  90. $fun = isset($_handler[$queue]) ? $_handler[$queue] : $_handler['file'];
  91. $queue_name = isset($this->options['queue_name']) ? $this->options['queue_name'] : 'think_queue';
  92. $value = $fun[0]($queue_name);
  93. if (!$value) {
  94. $value = [];
  95. }
  96. // 进列
  97. if (false === array_search($key , $value))
  98. array_push($value , $key);
  99. if (count($value) > $this->options['length']) {
  100. // 出列
  101. $key = array_shift($value);
  102. // 删除缓存
  103. $this->rm($key);
  104. if (APP_DEUBG) {
  105. //调试模式下,记录出列次数
  106. N($queue_name . '_out_times' , 1 , true);
  107. }
  108. }
  109. return $fun[1]($queue_name , $value);
  110. }
  111. }

Redis缓存驱动类(Thinkphp)

  1. namespace Think\Cache\Driver;
  2. use Think\Cache;
  3. class Redis extends Cache {
  4. /**
  5. * 架构函数
  6. * @param array $options 缓存参数
  7. * @access public
  8. */
  9. public function __construct($options=array()) {
  10. if ( !extension_loaded('redis') ) {
  11. E(L('_NOT_SUPPERT_').':redis');
  12. }
  13. if(empty($options)) {
  14. $options = array (
  15. 'host' => C('REDIS_HOST') ? C('REDIS_HOST') : '127.0.0.1',
  16. 'port' => C('REDIS_PORT') ? C('REDIS_PORT') : 6379,
  17. 'timeout' => C('DATA_CACHE_TIMEOUT') ? C('DATA_CACHE_TIMEOUT') : false,
  18. 'persistent' => false,
  19. );
  20. }
  21. $this->options = $options;
  22. $this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
  23. $this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
  24. $this->options['length'] = isset($options['length'])? $options['length'] : 0;
  25. $func = $options['persistent'] ? 'pconnect' : 'connect';
  26. $this->handler = new \Redis;
  27. $options['timeout'] === false ?
  28. $this->handler->$func($options['host'], $options['port']) :
  29. $this->handler->$func($options['host'], $options['port'], $options['timeout']);
  30. }
  31. /**
  32. * 读取缓存
  33. * @access public
  34. * @param string $name 缓存变量名
  35. * @return mixed
  36. */
  37. public function get($name) {
  38. N('cache_read',1);
  39. $value = $this->handler->get($this->options['prefix'].$name);
  40. $jsonData = json_decode( $value, true );
  41. return ($jsonData === NULL) ? $value : $jsonData; //检测是否为JSON数据 true 返回JSON解析数组, false返回源数据
  42. }
  43. /**
  44. * 写入缓存
  45. * @access public
  46. * @param string $name 缓存变量名
  47. * @param mixed $value 存储数据
  48. * @param integer $expire 有效时间(秒)
  49. * @return boolean
  50. */
  51. public function set($name, $value, $expire = null) {
  52. N('cache_write',1);
  53. if(is_null($expire)) {
  54. $expire = $this->options['expire'];
  55. }
  56. $name = $this->options['prefix'].$name;
  57. //对数组/对象数据进行缓存处理,保证数据完整性
  58. $value = (is_object($value) || is_array($value)) ? json_encode($value) : $value;
  59. if(is_int($expire)) {
  60. $result = $this->handler->setex($name, $expire, $value);
  61. }else{
  62. $result = $this->handler->set($name, $value);
  63. }
  64. if($result && $this->options['length']>0) {
  65. // 记录缓存队列
  66. $this->queue($name);
  67. }
  68. return $result;
  69. }
  70. /**
  71. * 删除缓存
  72. * @access public
  73. * @param string $name 缓存变量名
  74. * @return boolean
  75. */
  76. public function rm($name) {
  77. return $this->handler->delete($this->options['prefix'].$name);
  78. }
  79. /**
  80. * 清除缓存
  81. * @access public
  82. * @return boolean
  83. */
  84. public function clear() {
  85. return $this->handler->flushDB();
  86. }
  87. }

KEY的配置类

  1. /**
  2. * Redis内相关的key映射类
  3. */
  4. class RedisKeyMap {
  5. /**
  6. * 获取积分key值
  7. */
  8. public static function getProfileKey($bizType, $bizNo) {
  9. return self::getKey( $bizType, $bizNo );
  10. }
  11. /**
  12. * 获取key值
  13. */
  14. protected static function getKey( $type, $bizType, $bizNo ) {
  15. return implode( ':', [$type, $bizType, $bizNo] );
  16. }
  17. }

示列

  1. // 配置,可以写进配置文件里面;
  2. $option = [
  3. 'host' => '192.168.3.55' ,
  4. 'port' => 6379,
  5. 'timeout' => false,
  6. 'length' => 10 ,
  7. 'expire' => 360,
  8. 'queue_name' => 'testQueue',
  9. 'prefix' => 'zxg_', //出于安全性考虑给缓存key加上前缀;
  10. ];
  11. $cache = \Think\Cache::getInstance('redis',$option);
  12. $cache->name = 'zxg';
  13. echo $cache->name; // zxg
  14. unset($cache->name);
  15. $cache->name; // false; 不存在;
  16. // 队列,只保存前十个
  17. for($i=0;$i<=100;$i++){
  18. $str = microtime();
  19. $key = 'key_'.$str;
  20. $cache->set($key,$i.':'.$str);
  21. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注