php使用redis的blPop/brPop,一台服务器同时只能执行一次?
phpcn_u1582
phpcn_u1582 2017-05-16 12:59:45
[PHP讨论组]

服务器是使用 nginx + php-fpm 的架构,redis用的是connect来连接,每个网络请求应该都会有单独的php-fpm进程。我写了一个 循环,循环中有blPop/brPopsleep(5) 。浏览器先后开了两个标签页跑,然后 lpush 了4个数据进 list 发现总是先跑的那个标签页能读到前两个数据。也就是说blPop/brPop堵塞了整个服务器的所有其它侦听同一key的blPop/brPop
以下是我测试的代码:

//堵塞出队列
public function test(){
    tool::load('hRedis.php');
    $timeOut = 20;//堵塞20秒

    $cn = 'test_blist';

    $ress = [];
    for($i=0;$i<2;$i++){
        $ress[] = hRedis::cacheListBPop($cn,$timeOut);//这里面封装了redis的blPop/brPop
        sleep(5);
    }

    print_r($ress);
}

为什么在 先跑的进程的sleep 期间,后跑的进程还会被堵塞?

又做了进一步的测试,把循环去掉了,每个进程只执行一次,并且每次读取完 使用 redis->close() 发现两个进程的结束时间,还是相差了16秒左右。

上一条测试,我又放到两台服务器上去测,这次不是同一台的两个进程了,而是两台服务器,发现两台服务器的结束时间,相差的秒数就是我插入两条数据相隔的时间!这次没有延迟了!

phpcn_u1582
phpcn_u1582

全部回复(2)
某草草

首先Redis是单线程的,任何发送到服务器端的请求都是排队按顺序执行. 所以你说的每个网络请求应该都会有单独的进程,我认为是不正确的.
blPop指令是阻塞客户端的,而非服务器端,不然对于单线程的Redis来说是致命的.
你打开两标签页后,就等于打开了2个客户端. 在你打开2个标签后没有push数据之前,这2个客户端都处于阻塞状态,你的阻塞时间设置了20秒.
当你push数据到list后,这2个客户端对同一个键执行brpop操作,那么最先执行brpop命令的客户端可以获取pop的值,也就是第1个标签页.sleep 5s,再pop一个数据, 之后就输出,第一个客户端执行完退出后,如果第二个客户端还在执行着pop那行的话,我想应该会输出后续的值的,如果2个客户端打开间隔很短,估计也就退出了. 你可以调整2个客户端的打开时间间隔测试一下. 然后告诉我答案. 谢谢

天蓬老师

"网络请求应该都会有单独的进程"这句话有误,已经改成“每个网络请求应该都会有单独的php-fpm进程”。
第二个问题是你说的那样,第二个客户端会输出后续的值,但是第二个客户端输出值的时间,比第一个客户端平均晚了16秒,我想知道为什么会晚这么多,能不能缩短?还有第二个客户端为什么不能和第一个客户端同时监听?

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号