单例模式封装Redis操作类

为什么要封装Redis的操作类

原因非常简单, 使用过Redis的都知道, 通常我们set一个数据需要以下几步操作

?
1
2
3
4
5
6
7
$ip = '127.0.0.1';
$port = 6379;
$redis = new Redis();
$redis->pconnect($ip, $port, 1);
$key = "test";
$value = "this is test";
$redis->set($key, $value);
如果项目真的很小, 只有几处用到Redis的操作, 那么以上的操作完全可以每次都写一遍

但是项目只要不是很小, 就会遇到维护和管理的问题, 把这些什么new, connect, close全部抽象成gateway, 封装缓存单例, 封装底层驱动等等就很有必要了

当然, 网上已经有无数多的轮子了, 直接用现成的轮子完全没有任何毛病, 出于学习的目的, 造一个玩具车, 遥控车也不是不行, 嘻嘻

封装Redis操作类
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Rds
{
    private static $redis;
    private static $instance;
    private static $status;
 
    private function __construct()
    {
        self::$redis = new \Redis();
        self::$status = self::$redis->pconnect('127.0.0.1', 6379, 1);
    }
 
    public static function __callStatic($name, $arguments) {
        !self::$instance && self::$instance = new self;
        return self::$status ? self::$instance->$name($arguments) : false;
    }
 
    private function exists($e) {
        return self::$redis->exists($e[0]);
    }
 
    private function get($e) {
        return json_decode(self::$redis->get($e[0]), true);
    }
 
    private function set($e) {
        return self::$redis->set($e[0], json_encode($e[1], 320));
    }
 
    private function setex($e) {
        return self::$redis->setex($e[0], $e[1], json_encode($e[2], 320));
    }
 
    public function __destruct()
    {
        self::$redis->close();
    }
}
造一个玩具车就是这么简单, 调用方法如下:
?
1
2
3
4
Rds::exists('key')
Rds::get('key');
Rds::set('key', ['foo' => 'bar']);
Rds::setex('key', 60, ['foo' => 'bar']);

看看上面调用方法写起来是不是让人感觉心旷神怡? 哈哈哈 妈妈再也不用担心我写一堆乱七八糟的代码了

封装注解

简单说一下这个类是如何封装的

首先我使用了__callStatic魔术方法, 因为Redis每次都需要去new一下(new真的是我贼讨厌的一个操作, 我就喜欢静态调用) 所以直接用一个魔术方法接受外部调用的静态方法

然后在魔术方法中判断一下是否已初始化, 并将Rds实例保存至属性中, 然后第一次初始化时, 构造方法中new Redis, 将redis实例存入属性中, 这样Rds类中的几个属性就既保存了自身的实例, 又保存了redis的实例

所以除了第一次调用Rds类外, 后面的重复调用Rds类, 都是直接从Rds类中的属性拿实例, 而不会再次实例化, 这样就完成了单例模式的封装

close的目的

最后, 补充一下析构函数中的close操作, 众所周知, pconnect即长连接, 还有一个操作是connect即短连接, 它们的区别是:

长连接只有在当前的FastCGI进程被PHP-FPM回收时才会被释放,长连接的生命周期就是当前FastCGI进程的生命周期(如果不知道什么是FastCGI和PHP-FPM, 先去百度谷歌一下, 作为一个PHPer, 这是必须了解的内容)

而短连接会在FastCGI进程每次接收到Web Server的请求后就会重新打开一个, 在执行完请求, 返回数据给WebServer后被释放

所以可以看出长连接的作用主要是用于连接复用,降低连接成本的, 手动close就是出于此目的

close不是真正释放当前的FastCGI进程与Redis的连接, 而是关闭当前连接, 让这个连接能够更快速地让其他客户端拿来复用, 避免因为当前连接没有关闭而一直占用着一个连接, 其他客户端就必须新建连接, 那这个连接就浪费了

发布评论
还没有评论,快来抢沙发吧!