PHP使用Redis長(zhǎng)連接的方法詳解
本文實(shí)例講述了PHP使用Redis長(zhǎng)連接的方法。分享給大家供大家參考,具體如下:
php-redis在github上的項(xiàng)目地址:https://github.com/phpredis/phpredis
pconnect函數(shù)聲明
其中time_out表示客戶端閑置多少秒后,就斷開(kāi)連接。函數(shù)連接成功返回true,失敗返回false:
pconnect(host, port, time_out, persistent_id, retry_interval) host: string. can be a host, or the path to a unix domain socket port: int, optional timeout: float, value in seconds (optional, default is 0 meaning unlimited) persistent_id: string. identity for the requested persistent connection retry_interval: int, value in milliseconds (optional)
下面的例子詳細(xì)介紹了pconnect連接的重用情況。
$redis->pconnect('127.0.0.1', 6379); $redis->pconnect('127.0.0.1'); // 默認(rèn)端口6379,跟上面的例子使用相同的連接。 $redis->pconnect('127.0.0.1', 6379, 2.5); // 設(shè)置了2.5秒的過(guò)期時(shí)間。將是不同于上面的新連接 $redis->pconnect('127.0.0.1', 6379, 2.5, 'x'); //設(shè)置了持久連接的id,將是不同于上面的新連接 $redis->pconnect('/tmp/redis.sock'); // unix domain socket - would be another connection than the four before.
pconnect使用介紹
對(duì)pconnect方法簡(jiǎn)單描述
使用該方法創(chuàng)建連接,連接不會(huì)在調(diào)用close方法之后關(guān)閉,只有在進(jìn)程結(jié)束之后該連接才會(huì)被關(guān)閉。
[待驗(yàn)證]如果使用的是長(zhǎng)連接,Redis配置文件中的timeout配置項(xiàng)需要設(shè)置為0,否則連接池中的連接會(huì)因?yàn)槌瑫r(shí)而失效
針對(duì)PHP-FPM來(lái)說(shuō)明一下pconnect
長(zhǎng)連接只會(huì)在PHP-FPM進(jìn)程結(jié)束之后結(jié)束,連接的生命周期就是PHP-FPM進(jìn)程的生命周期。
相比較短連接而言,在每一個(gè)PHP-FPM調(diào)用過(guò)程中都會(huì)產(chǎn)生一個(gè)redis的連接,在服務(wù)器上的表性形式就是過(guò)多的time_out連接狀態(tài)。
而長(zhǎng)連接相反,PHP-FPM調(diào)用的所有CGI都只會(huì)共用一個(gè)長(zhǎng)連接,所以也就是只會(huì)產(chǎn)生固定數(shù)量的time_out。
關(guān)閉長(zhǎng)連接
可以調(diào)用close和unset方法,但兩則差異很大:
- close的作用僅僅是使當(dāng)前PHP進(jìn)程不能再進(jìn)行redis請(qǐng)求,但無(wú)法真正關(guān)閉redis長(zhǎng)連接,連接在后續(xù)請(qǐng)求中仍然會(huì)被重用,直FPM進(jìn)程生命周期結(jié)束。所以close 并不會(huì)銷毀redis對(duì)象,只是斷開(kāi)連接而已。
- unset 變量才會(huì)銷毀。也需要注意并不是使用了 pconnect 就不要 close 了,如果當(dāng)前腳本執(zhí)行時(shí)間很長(zhǎng) 那么也會(huì)一直占用一個(gè)連接的。
如何判斷當(dāng)前Redis是否處于連接狀態(tài)
等效的問(wèn)題是,在單例模式中,判斷當(dāng)前實(shí)例是否有效。
習(xí)慣上調(diào)用echo,判斷是否正常返回字符串本身,或者調(diào)用ping,查看返回值是否為 +PONG。
但是需要特別小心的是,在redis斷開(kāi)連接之后,調(diào)用echo以及ping(返回'+POMG')時(shí),均會(huì)拋出異常。所以要通過(guò)異常捕獲機(jī)制來(lái)處理。
代碼分析pconnect連接重用的問(wèn)題
情況一:非單例模式。
說(shuō)明:a實(shí)例和b實(shí)例共用了一條連接,b實(shí)例將a實(shí)例的連接修改了:
所以下面的例子導(dǎo)致最終$a實(shí)例得到的值變成了2,需要特別注意。
$a = pconnect(host, port, time_out); select(3); $a -> setex(id, 3); echo $a -> get(id); //之后執(zhí)行下面的連接 $b = pconnect(host, port, time_out); select(2); $b->set(id,2) echo $a->get(id); //這個(gè)id操作的db變成了2,不再是之前的3了。因?yàn)檫@兩個(gè)連接共用了一個(gè)連接通道。
情況二:?jiǎn)卫J健?/strong>
將上述的代碼修改,a和b都通過(guò)getInstance來(lái)生成。生成的前提是判斷當(dāng)前實(shí)例是否存在。單例模式的混淆點(diǎn)在于:
$a生成了一個(gè)實(shí)例,這時(shí)候生成$b, $b使用了$a的實(shí)例,然后修改了$a的連接,之后調(diào)用$a肯定是調(diào)用的$b修改之后的實(shí)例。跟情況二一致。
單例模式的代碼如下:
public static function getInstance($db = 0) { if (!isset(self::$_instance)) { self::$_instance = new Redis(); } self::_connect(); self::$_instance->select($db); return self::$_instance; }
兩種情況都說(shuō)明了連接重用的問(wèn)題。如何修復(fù)這個(gè)bug??jī)牲c(diǎn):
1.為每一個(gè)db生成一個(gè)單例。
2.避免連接重用問(wèn)題。
所以代碼可以做調(diào)整為返回一個(gè)單例數(shù)組:
public static function getInstance($db = 0) { try{ if (isset(self::$_instance[$db]) && self::$_instance[$db]->Ping() == 'Pong') { return self::$_instance[$db]; } } catch (Exception $e) { } self::$_instance[$db] = new Redis(); self::_connect($db); return self::$_instance[$db]; }
需要注意的地方
避免在Task類成員變量中使用redis對(duì)象。
在redis的單例模式中,聲明了time_out的過(guò)期時(shí)間。如果redis處理的場(chǎng)合是一個(gè)任務(wù),而任務(wù)調(diào)用redis間隔時(shí)間又比較長(zhǎng)。當(dāng)間隔大于time_out時(shí)候,redis就會(huì)斷開(kāi)連接,這時(shí)候所有對(duì)redis的操作都會(huì)失效。解決的辦法就是避免這種調(diào)用方式,通過(guò)在調(diào)用的地方動(dòng)態(tài)聲明redis類來(lái)執(zhí)行。這種問(wèn)題對(duì)于長(zhǎng)連接和短鏈接是沒(méi)有區(qū)分,屬于調(diào)用的方式錯(cuò)誤。
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php+redis數(shù)據(jù)庫(kù)程序設(shè)計(jì)技巧總結(jié)》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《PHP基本語(yǔ)法入門(mén)教程》、《PHP數(shù)組(Array)操作技巧大全》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
- PHP長(zhǎng)連接實(shí)現(xiàn)與使用方法詳解
- PHP擴(kuò)展模塊memcached長(zhǎng)連接使用方法分析
- 基于php實(shí)現(xiàn)長(zhǎng)連接的方法與注意事項(xiàng)的問(wèn)題
- PHP set_time_limit(0)長(zhǎng)連接的實(shí)現(xiàn)分析
- 基于HTTP長(zhǎng)連接的"服務(wù)器推"技術(shù)的php 簡(jiǎn)易聊天室
- PHP編程實(shí)現(xiàn)的TCP服務(wù)端和客戶端功能示例
- php實(shí)現(xiàn)TCP端口檢測(cè)的方法
- 詳解PHP Swoole長(zhǎng)連接常見(jiàn)問(wèn)題
相關(guān)文章
一個(gè)基于PDO的數(shù)據(jù)庫(kù)操作類(新) 一個(gè)PDO事務(wù)實(shí)例
原先已經(jīng)寫(xiě)過(guò)一個(gè)PDO的數(shù)據(jù)庫(kù)操作類,這次只是在原先基礎(chǔ)上進(jìn)行修改。2011-07-07PHP實(shí)現(xiàn)簡(jiǎn)單實(shí)用的驗(yàn)證碼類
這篇文章主要介紹了PHP實(shí)現(xiàn)簡(jiǎn)單實(shí)用的驗(yàn)證碼類,包含驗(yàn)證碼常用的隨機(jī)驗(yàn)證碼、干擾線、圖片生成與輸出等相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07php中CI操作多個(gè)數(shù)據(jù)庫(kù)的代碼
最近有個(gè)需求,做一個(gè)獨(dú)立后臺(tái)出來(lái),這個(gè)獨(dú)立后臺(tái)有單獨(dú)的庫(kù),單獨(dú)的url,單獨(dú)…。但是,這里邊只是一些基礎(chǔ)數(shù)據(jù),而使用者需要通過(guò)該庫(kù)查看另一個(gè)庫(kù)里的統(tǒng)計(jì)數(shù)據(jù)。這就帶來(lái)一個(gè)問(wèn)題:我需要在控制器里邊可以同時(shí)操作兩個(gè)數(shù)據(jù)庫(kù),而且這兩個(gè)庫(kù)毫不相干2012-07-07php性能優(yōu)化進(jìn)階不要在for循環(huán)中操作DB
這篇文章主要為大家介紹了php性能優(yōu)化進(jìn)階不要在for循環(huán)中操作DB,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06簡(jiǎn)單談?wù)刾hp中ob_flush和flush的區(qū)別
本文簡(jiǎn)單的對(duì)php中ob_flush和flush進(jìn)行了對(duì)比分析,得出了他們之間的區(qū)別,給需要的小伙伴參考下。2014-11-11