请选择 进入手机版 | 继续访问电脑版

Redis中国用户组(CRUG)论坛

 找回密码
 立即注册

扫一扫,访问微社区

搜索
热搜: 活动 交友 discuz
查看: 16763|回复: 1

redis短连接和长连接

[复制链接]
  • TA的每日心情
    开心
    2016-5-31 17:57
  • 签到天数: 1 天

    [LV.1]初来乍到

    1

    主题

    2

    帖子

    31

    积分

    新手上路

    Rank: 1

    积分
    31
    QQ
    发表于 2016-6-1 09:09:32 | 显示全部楼层 |阅读模式
    本文介绍了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的连接。

  • TA的每日心情
    开心
    2016-11-10 10:06
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    0

    主题

    15

    帖子

    188

    积分

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    188
    QQ
    发表于 2016-11-2 10:04:02 | 显示全部楼层
    新手,好多看不懂呢
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    Archiver|手机版|小黑屋|Redis中国用户组 ( 京ICP备15003959号

    GMT+8, 2019-10-19 18:16 , Processed in 0.088434 second(s), 26 queries .

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表