服務(wù)器是使用 nginx
php-fpm
的架構(gòu),redis用的是connect來連接,每個(gè)網(wǎng)絡(luò)請(qǐng)求應(yīng)該都會(huì)有單獨(dú)的php-fpm
進(jìn)程。我寫了一個(gè) 循環(huán),循環(huán)中有blPop/brPop
和 sleep(5)
。瀏覽器先后開了兩個(gè)標(biāo)簽頁跑,然后 lpush
了4個(gè)數(shù)據(jù)進(jìn) list
發(fā)現(xiàn)總是先跑的那個(gè)標(biāo)簽頁能讀到前兩個(gè)數(shù)據(jù)。也就是說blPop/brPop
堵塞了整個(gè)服務(wù)器的所有其它偵聽同一key的blPop/brPop
?
以下是我測(cè)試的代碼:
//堵塞出隊(duì)列
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);
}
為什么在 先跑的進(jìn)程的sleep 期間,后跑的進(jìn)程還會(huì)被堵塞?
又做了進(jìn)一步的測(cè)試,把循環(huán)去掉了,每個(gè)進(jìn)程只執(zhí)行一次,并且每次讀取完 使用 redis->close()
發(fā)現(xiàn)兩個(gè)進(jìn)程的結(jié)束時(shí)間,還是相差了16秒左右。
上一條測(cè)試,我又放到兩臺(tái)服務(wù)器上去測(cè),這次不是同一臺(tái)的兩個(gè)進(jìn)程了,而是兩臺(tái)服務(wù)器,發(fā)現(xiàn)兩臺(tái)服務(wù)器的結(jié)束時(shí)間,相差的秒數(shù)就是我插入兩條數(shù)據(jù)相隔的時(shí)間!這次沒有延遲了!
首先Redis是單線程的,任何發(fā)送到服務(wù)器端的請(qǐng)求都是排隊(duì)按順序執(zhí)行. 所以你說的每個(gè)網(wǎng)絡(luò)請(qǐng)求應(yīng)該都會(huì)有單獨(dú)的進(jìn)程,我認(rèn)為是不正確的.
blPop指令是阻塞客戶端的,而非服務(wù)器端,不然對(duì)于單線程的Redis來說是致命的.
你打開兩標(biāo)簽頁后,就等于打開了2個(gè)客戶端. 在你打開2個(gè)標(biāo)簽后沒有push數(shù)據(jù)之前,這2個(gè)客戶端都處于阻塞狀態(tài),你的阻塞時(shí)間設(shè)置了20秒.
當(dāng)你push數(shù)據(jù)到list后,這2個(gè)客戶端對(duì)同一個(gè)鍵執(zhí)行brpop操作,那么最先執(zhí)行brpop命令的客戶端可以獲取pop的值,也就是第1個(gè)標(biāo)簽頁.sleep 5s,再pop一個(gè)數(shù)據(jù), 之后就輸出,第一個(gè)客戶端執(zhí)行完退出后,如果第二個(gè)客戶端還在執(zhí)行著pop那行的話,我想應(yīng)該會(huì)輸出后續(xù)的值的,如果2個(gè)客戶端打開間隔很短,估計(jì)也就退出了. 你可以調(diào)整2個(gè)客戶端的打開時(shí)間間隔測(cè)試一下. 然后告訴我答案. 謝謝
"網(wǎng)絡(luò)請(qǐng)求應(yīng)該都會(huì)有單獨(dú)的進(jìn)程"這句話有誤,已經(jīng)改成“每個(gè)網(wǎng)絡(luò)請(qǐng)求應(yīng)該都會(huì)有單獨(dú)的php-fpm
進(jìn)程”。
第二個(gè)問題是你說的那樣,第二個(gè)客戶端會(huì)輸出后續(xù)的值,但是第二個(gè)客戶端輸出值的時(shí)間,比第一個(gè)客戶端平均晚了16秒,我想知道為什么會(huì)晚這么多,能不能縮短?還有第二個(gè)客戶端為什么不能和第一個(gè)客戶端同時(shí)監(jiān)聽?