一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - PHP教程 - PHP使用Redis長連接的方法詳解

PHP使用Redis長連接的方法詳解

2019-10-21 11:37發飆的小蝸牛 PHP教程

這篇文章主要介紹了PHP使用Redis長連接的方法,結合實例形式詳細分析php操作redis長連接的使用方法及相關注意事項,需要的朋友可以參考下

本文實例講述了PHP使用Redis長連接的方法。分享給大家供大家參考,具體如下:

php-redis在github上的項目地址:https://github.com/phpredis/phpredis

pconnect函數聲明

其中time_out表示客戶端閑置多少秒后,就斷開連接。函數連接成功返回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)

下面的例子詳細介紹了pconnect連接的重用情況。

$redis->pconnect('127.0.0.1', 6379);
$redis->pconnect('127.0.0.1'); // 默認端口6379,跟上面的例子使用相同的連接。
$redis->pconnect('127.0.0.1', 6379, 2.5); // 設置了2.5秒的過期時間。將是不同于上面的新連接
$redis->pconnect('127.0.0.1', 6379, 2.5, 'x'); //設置了持久連接的id,將是不同于上面的新連接
$redis->pconnect('/tmp/redis.sock'); // unix domain socket - would be another connection than the four before.

pconnect使用介紹

對pconnect方法簡單描述

使用該方法創建連接,連接不會在調用close方法之后關閉,只有在進程結束之后該連接才會被關閉。

[待驗證]如果使用的是長連接,Redis配置文件中的timeout配置項需要設置為0,否則連接池中的連接會因為超時而失效

針對PHP-FPM來說明一下pconnect

長連接只會在PHP-FPM進程結束之后結束,連接的生命周期就是PHP-FPM進程的生命周期。
相比較短連接而言,在每一個PHP-FPM調用過程中都會產生一個redis的連接,在服務器上的表性形式就是過多的time_out連接狀態。
而長連接相反,PHP-FPM調用的所有CGI都只會共用一個長連接,所以也就是只會產生固定數量的time_out。

關閉長連接

可以調用close和unset方法,但兩則差異很大:

close的作用僅僅是使當前PHP進程不能再進行redis請求,但無法真正關閉redis長連接,連接在后續請求中仍然會被重用,直FPM進程生命周期結束。所以close 并不會銷毀redis對象,只是斷開連接而已。

unset 變量才會銷毀。也需要注意并不是使用了 pconnect 就不要 close 了,如果當前腳本執行時間很長 那么也會一直占用一個連接的。

如何判斷當前Redis是否處于連接狀態

等效的問題是,在單例模式中,判斷當前實例是否有效。

習慣上調用echo,判斷是否正常返回字符串本身,或者調用ping,查看返回值是否為 +PONG。

但是需要特別小心的是,在redis斷開連接之后,調用echo以及ping(返回'+POMG')時,均會拋出異常。所以要通過異常捕獲機制來處理。

代碼分析pconnect連接重用的問題

情況一:非單例模式。

說明:a實例和b實例共用了一條連接,b實例將a實例的連接修改了:
所以下面的例子導致最終$a實例得到的值變成了2,需要特別注意。

$a = pconnect(host, port, time_out);
select(3);
$a -> setex(id, 3);
echo $a -> get(id);
//之后執行下面的連接
$b = pconnect(host, port, time_out);
select(2);
$b->set(id,2)
echo $a->get(id);  //這個id操作的db變成了2,不再是之前的3了。因為這兩個連接共用了一個連接通道。

情況二:單例模式。

將上述的代碼修改,a和b都通過getInstance來生成。生成的前提是判斷當前實例是否存在。單例模式的混淆點在于:

$a生成了一個實例,這時候生成$b, $b使用了$a的實例,然后修改了$a的連接,之后調用$a肯定是調用的$b修改之后的實例。跟情況二一致。
單例模式的代碼如下:

public static function getInstance($db = 0)
{
  if (!isset(self::$_instance)) {
    self::$_instance = new Redis();
  }
  self::_connect();
  self::$_instance->select($db);
  return self::$_instance;
}

兩種情況都說明了連接重用的問題。如何修復這個bug?兩點:

1.為每一個db生成一個單例。
2.避免連接重用問題。

所以代碼可以做調整為返回一個單例數組:

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對象。

在redis的單例模式中,聲明了time_out的過期時間。如果redis處理的場合是一個任務,而任務調用redis間隔時間又比較長。當間隔大于time_out時候,redis就會斷開連接,這時候所有對redis的操作都會失效。解決的辦法就是避免這種調用方式,通過在調用的地方動態聲明redis類來執行。這種問題對于長連接和短鏈接是沒有區分,屬于調用的方式錯誤。

希望本文所述對大家PHP程序設計有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产一级精品高清一级毛片 | 亚洲国产黄色 | 娇喘嗯嗯 轻点啊视频福利 九九九九在线精品免费视频 | 波多野结衣同性系列698 | 麻豆最新地址 | 欧美色成人tv在线播放 | 欧美人伦禁忌.5 | a色在线 | 四虎精品成人a在线观看 | 草莓视频旧版本 | 欧美日韩亚毛片免费观看 | 农村妇女野战bbxxx | 国产精品露脸国语对白99 | 亚洲美女人黄网成人女 | 国产麻豆剧果冻传媒观看免费视频 | 男人猛进猛出女人下面视频 | 好爽视频| 欧美灰丝袜丝交nylons | 亚洲29p| 插入肥臀| 日本一区免费观看 | 亚洲国产第一区二区香蕉日日 | 亚飞与亚基国语1080p在线观看 | 爆操美女| 午夜理论电影在线观看亚洲 | 久久精品一卡二卡三卡四卡视频版 | 亚洲乱码尤物193yw在线播放 | 欧美日韩成人在线 | 美女张开腿让男人桶的 视频 | 亚洲一区二区日韩欧美gif | 免费观看视频在线 | 欧美一级鲁丝片免费看 | 精品久久久久久国产 | 亚洲福利一区二区三区 | 成人私人影院在线观看网址 | 无耻三级在线观看 | 国产一区二区三区福利 | 好大用力深一点视频 | 欧乱色国产精品兔费视频 | 欧美一区二区三区不卡视频 | 国产农村乱子伦精品视频 |