我在用Laravel框架,然后用redis,发现如果Redis::connection('config1')通过配置文件获取的redis连接,如果进行select后,会把之前的连接库的一并改变。
'config1' => [
'host' => 'xx',
'password' => 'xx',
'port' => 'xx',
'database' => 2
]
$a = Redis::connection('config1');
$b = Redis::connection('config1');
$b->select(3);
$a->set('test1', 1);
这个时候 test1 会加到3库下
看了下源码也没看出这个是哪里的问题,到底是Laravel问题还是Predis问题呢? 我理解这个$b->select 不应该影响$a的才对啊。 请大佬赐教
Predis: 1.1.7
PHP 5.6.13
Redis Server 2.6.10
Laravel 5.4.17
打开
\Illuminate\Support\Facades\Redis
的代码,看到getFacadeAccessor
方法返回了redis
。然后使用
dd(get_class(app('redis')))
可以看到,redis
是由\Illuminate\Redis\RedisManager
来实现的。现在打开
\Illuminate\Redis\RedisManager
的代码,找到connection
方法。可以清楚的看到,对于同一个名字的连接,laravel 会在首次解析后,就把它保存起来。
下次需要的时候直接返回,也就是说,同样的
name
,每次调用 connection 都是返回的同一个 Redis 实例。这样就解释的通了吧。
那如果你非想要呢?那你可以试试clone
因为一些对象被克隆后,会存在一些问题,所以类本身可以通过实现
__clone
这个魔术方法,通过将这个魔术方法设置成私有或者在内部抛异常来阻止对象实例被克隆。就以这里的 Redis 连接为例,如果允许被克隆,其实际上也是克隆的同一个 Redis 连接而已,在同一个 Redis 连接中,任意一个对象实例发送命令势必时会影响到其他对象实例持有的同一连接,换句话说,如果你想完全区分两个对象实例,那就应该创建一个新的连接。
在这里,可以使用
resolve
方法,来创建一个新的连接,这样就不会有问题了。