V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
barbery
V2EX  ›  问与答

关于redis的pconnect和connect使用场景有什么不同?

  •  
  •   barbery · 2014-01-04 14:57:27 +08:00 · 16133 次点击
    这是一个创建于 3977 天前的主题,其中的信息可能已经有所发展或是发生改变。
    关于redis的pconnect和connect,使用场景有什么不同?或者说,什么时候该用pconnect,什么时候用connect?

    我简单的用ab测试下,pconnect的结果比connect的好20%左右,俗话说有利必有弊,pconnect的弊端在哪呢?
    3 条回复    1970-01-01 08:00:00 +08:00
    ETiV
        1
    ETiV  
       2014-01-04 16:13:36 +08:00   ❤️ 3
    Short Version:

    如果你的应用/服务, 可以有独立的进程, 使用自己的内存, 就可以放心地用 pconnect.

    ===============

    Story Version:

    几个月前, 同事遇到了这么一个 pconnect on php 的坑:

    一台机器上跑了俩 HTTP 服务, 分别连接了同一个 Redis 服务器, 使用了的两个 DB.

    DB 的结构一样, 但内容不一样.

    HTTP 环境用的是 Apache + mod_PHP.

    服务 A:

    ```
    $con = pconnect(...);

    $con->set(BLAH_KEY, ...);
    $con->set(ANOTHER_KEY, ...);

    $resp->send($con->get(SOME_KEY));
    ```

    服务 B:

    ```
    $con = pconnect(...);
    $con->select(2);

    $con->set(BLAH_KEY, ...);
    $con->set(ANOTHER_KEY, ...);

    $resp->send($con->get(SOME_KEY));
    ```

    俩服务都返回各自 DB 中 SOME_KEY 的结果.

    ----

    A, B服务启动后.

    1) 连续访问 A, 返回正常
    2) 再连续访问 B, 返回正常
    3) 再访问 A, 返回的结果都是 B 的.

    ----

    由于没空细研究 PHP 的 Redis 驱动是怎么写的, 所以当它是个黑盒子吧.

    所以猜了一下原因:

    驱动模块被 Apache 加载之后, 一直留在内存里.
    当使用了 pconnect 后, 驱动将保留这个连接, 和在这个连接上操作过的状态(比如 select), 以备下次使用.

    这就导致了 A 的代码中, 由于没有使用 select, 在访问 B 之后, A 中的 Redis 连接还在 B 的 DB 上.

    同时, 由于 A, B 代码中对 Redis 的操作不是原子的 (虽然很快), 所以仅仅在 A 上使用 select 也是不安全的.

    ----

    结果就是:

    把 A, B 代码里的 pconnect, 改成 connect. 问题解决.

    ----

    也许还可以用的其他解决方法, 来让 pconnect 工作正常(没试):

    让驱动认为这是两个不同的 Redis 服务:

    -- 再启动一个 Redis 服务, 另外占用一个端口.
    -- 做端口转发, 或者本机做一个 TCP 代理.
    -- 分配给它不同的 hostname (虽然各 hostname 指向同一个IP), 使驱动保存两个 pconnect 产生的连接.

    ----

    或许, 驱动层更应该做好这些东西, 比如: 按 HOST/PORT/DB 来保留 pconnect 得到的连接.
    barbery
        2
    barbery  
    OP
       2014-01-04 19:51:52 +08:00
    @ETiV 灰常感谢呐。。。
    pubby
        3
    pubby  
       2014-01-04 19:58:47 +08:00
    @ETiV 好坑! 好在我的redis都是随应用开独立服务进程的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2769 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 07:46 · PVG 15:46 · LAX 23:46 · JFK 02:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.