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

伺服器是使用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秒,我想知道為什麼會晚這麼多,能不能縮短?還有第二個客戶端為什麼不能跟第一個客戶同時監聽?

      最新下載
      更多>
      網站特效
      網站源碼
      網站素材
      前端模板
      關於我們 免責聲明 Sitemap
      PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!