Redis長短鏈接的區別


 

本文介紹了phpredis中與redis建立連接的兩種方式:connect(短連接)和pconnect(長連接)的區別。
問題背景:
項目采用LNMP架構,考慮到數據訪問性能問題,因此使用redis來做數據存儲,之前一直都是通過直連IP的方式來訪問redis,但是運維說redis用sentinel做的高可用,如果直連IP去訪問,高可用就無法生效了,因此決定切換成域名的訪問方式。
切換域名之后,問題就來了,很多接口出現調用超時的情況,在php-fpm的慢日志中可以看到超時接口的函數調用棧,接口的邏輯很簡單,只是從redis取一些數據出來,並沒有做其他事情,甚至連日志都沒打,為何會超時呢?
問題追蹤:
既然當天做了切換訪問方式的變更,就一定跟這個有關。切換前后唯一的區別就是切換成域名的訪問方式之后,每次連接redis需要先到域名服務器將域名解析成IP,然后再去連接,如果直連IP就可以省去域名解析的過程,難道是域名解析速度太慢導致超時?
問題定位:
寫了一個簡單的腳本,看了一下域名訪問和IP訪問的耗時差別到底多大,代碼如下,
//test.php
<?php
function microtime_float()
{
list($usec, $sec) = explode(” “, microtime());
return ((float)$usec + (float)$sec);
}

$begin = microtime_float();
$redis=new Redis();
$redis->connect(“10.100.24.198″,6380);
$end = microtime_float();
$ip_cost = intval(($end – $begin)*1000000);

$begin = microtime_float();
$redis->connect(“videogh-6380-redis1.m6.tudou.com”,6380);
$end = microtime_float();
$domain_cost = intval(($end – $begin)*1000000);

echo “ip costip_cost us,domain_costdomain_cost us\n”;

//結果
ip cost:514 us,domain_cost:26972 us
IP直連和域名連接的耗時竟然差了40倍之多!!難怪會有如此多的請求超時。
問題解決:
既然切換成域名后,與redis頻繁建立連接導致超時,因此考慮redis的長連接方式,即pconnect方式。注意,這里說的長連接和短連接,並不是指TCP和UDP,其實redis本身也只支持域套接字和TCP連接,這里說的長連接是指多次請求之間可以對redis連接進行復用,即只在第一次執行請求是建立連接,以后每次請求只是從連接池中將連接取出,不再重新建立連接;而短連接表示連接在多次請求之間不可復用,每次請求都需要重新建立連接。
理論上雖然可行,但還需要對pconnect的實際執行效果進行驗證,驗證過程如下。
驗證過程:
考慮用抓包和lsof兩種方式進行驗證,
准備工作
環境:
Linux+nginx+fpm+PHP5.5
將fpm的參數配置為
pm.max_children = 1;
pm.start_servers = 1;
pm.max_spare_servers = 1;
通過修改php-fpm的參數,將php-fpm的進程設置為一個,這樣就可以准確找到執行請求的php-fpm進程id,
頁面對應的php代碼
public function test_redis()
{
$redis = new Redis();
//redis->connect(“127.0.0.1”, 6379); //connect連接
redis->pconnect(“127.0.0.1”, 6379); //pconnect連接
exit();
}

1、lsof方式
先用pconnect的方式連接方式請求頁面的test_redis函數,並執行命令lsof –n –p (fpm-pid),查看php-fpm的句柄使用情況,如下圖所示
說明請求結束后,php-fpm中仍然保持與redis的連接,下次請求仍然可以對該連接進行復用;如果使用connect,則獲取不到連接信息。

2、抓包方式
抓包命令:tcpdump –i any –X –v –vv tcp and dst port 6379
同樣用connec方式和pconnect方式執行多次,通過抓包發現,使用connect方式連接每次都能抓到包,說明connect每次都會建立連接;使用pconnect方式連接只有第一次訪問的時候能抓到包,以后每次執行都抓不到包,說明連接只建立一次。
而且,當使用pconnect方式連接時,通過redis-cli連接到redis,並執行info clients,可以看到connected_clients=2,排除終端的命令行連接以外,還有一個是與php-fpm保持的長連接,說明即使請求結束,php-fpm仍然會保留與redis的連接;如果采用connect方式進行連接,則connected_clients=1,即請求結束后php-fpm就釋放了與redis的連接。

 

 

 

原文鏈接:http://bbs.redis.cn/forum.php?mod=viewthread&tid=721


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM