伺服器是使用 nginx
+ php-fpm
的架構,redis用的是connect來連接,每個網路請求應該都會有單獨的php-fpm
進程。我寫了一個 循環,循環中有blPop/brPop
和 sleep(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秒左右。
上一條測試,我又放到兩台伺服器上去測,這次不是同一台的兩個進程了,而是兩台伺服器,發現兩台伺服器的結束時間,相差的秒數就是我插入兩條數據相隔的時間!這次沒有延遲了!
首先Redis是單線程的,任何發送到伺服器端的請求都是排隊按順序執行. 所以你說的每個網絡請求應該都會有單獨的進程,我認為是不正確的.
blPop指令是阻塞客戶端的,而非伺服器端,不然對於單線程的Redis來說是致命的.
你打開兩個標籤頁後,就等於打開了2個客戶端. 在你打開2個標籤後沒有push數據之前,這2個客戶端都處於阻塞狀態,你的阻塞時間設定了20秒.
當你push資料到list後,這2個客戶端對同一個鍵執行brpop操作,那麼最先執行brpop指令的客戶端可以取得pop的值,也就是第1個標籤頁.sleep 5s,再pop一個資料, 之後就輸出,第一個客戶端執行完退出後,如果第二個客戶端還在執行著pop那行的話,我想應該會輸出後續的值的,如果2個客戶端打開間隔很短,估計也就退出了. 你可以調整2個客戶端的打開時間間隔測試一下. 然後告訴我答案. 謝謝
"網路請求應該都會有單獨的進程"這句話有誤,已經改成「每個網路請求應該都會有單獨的
php-fpm
進程」。第二個問題是你說的那樣,第二個客戶端會輸出後續的值,但是第二個客戶端輸出值的時間,比第一個客戶端平均晚了16秒,我想知道為什麼會晚這麼多,能不能縮短?還有第二個客戶端為什麼不能跟第一個客戶同時監聽?