laravel框架下redis連接共享及select方法的影響
在Laravel框架中使用redis時(shí),開(kāi)發(fā)者可能會(huì)遇到一個(gè)問(wèn)題:通過(guò)配置文件獲取的Redis連接,在使用select方法切換數(shù)據(jù)庫(kù)后,會(huì)影響到之前獲取的相同連接。本文將分析此問(wèn)題并提供解決方案。
問(wèn)題描述:假設(shè)代碼通過(guò)Redis::connection(‘config1’)獲取名為’config1’的Redis連接,其配置如下:
'config1' => [ 'host' => 'xx', 'password' => 'xx', 'port' => 'xx', 'database' => 2 ]
分別獲取兩次’config1’連接,并在其中一個(gè)連接上執(zhí)行select(3)切換到數(shù)據(jù)庫(kù)3:
$a = Redis::connection('config1'); $b = Redis::connection('config1'); $b->select(3); $a->set('test1', 1); // 'test1'寫入數(shù)據(jù)庫(kù)3,而非預(yù)期數(shù)據(jù)庫(kù)2
$a->set(‘test1’, 1)的結(jié)果令人意外,因?yàn)轭A(yù)期數(shù)據(jù)應(yīng)寫入數(shù)據(jù)庫(kù)2。這是因?yàn)長(zhǎng)aravel框架的Redis連接管理機(jī)制導(dǎo)致$a和$b實(shí)際上引用的是同一個(gè)Redis連接對(duì)象。
Laravel框架的IlluminateSupportFacadesRedis facade 通過(guò)getFacadeAccessor方法返回redis,而redis是由IlluminateRedisRedisManager實(shí)現(xiàn)的。IlluminateRedisRedisManager的connection方法會(huì)在首次解析后緩存連接,后續(xù)調(diào)用會(huì)直接返回相同的Redis實(shí)例。
因此,要避免此問(wèn)題,不能多次調(diào)用Redis::connection()來(lái)獲取獨(dú)立連接。解決方案是使用Laravel的resolve方法創(chuàng)建新的連接實(shí)例:
$a = app('redis')->connection('config1'); $b = app('redis')->connection('config1'); $b->select(3); $a->set('test1', 1); // 'test1'現(xiàn)在將寫入數(shù)據(jù)庫(kù)2
使用app(‘redis’)->connection(‘config1’)每次都會(huì)創(chuàng)建一個(gè)新的連接實(shí)例,從而避免共享同一個(gè)底層Redis連接的問(wèn)題,確保每個(gè)連接擁有獨(dú)立的數(shù)據(jù)庫(kù)選擇。 這解決了select方法影響其他連接的問(wèn)題。