php使用redis的blPop/brPop,一台伺服器同時只能執行一次?
phpcn_u1582
phpcn_u1582 2017-05-16 12:59:45
0
2
784

伺服器是使用 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個客戶端的打開時間間隔測試一下. 然後告訴我答案. 謝謝

Peter_Zhu

"網路請求應該都會有單獨的進程"這句話有誤,已經改成「每個網路請求應該都會有單獨的php-fpm進程」。
第二個問題是你說的那樣,第二個客戶端會輸出後續的值,但是第二個客戶端輸出值的時間,比第一個客戶端平均晚了16秒,我想知道為什麼會晚這麼多,能不能縮短?還有第二個客戶端為什麼不能跟第一個客戶同時監聽?

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板