天天看點

redis slaveof自己會發生什麼

向2.8版本redis發送slaveof,将自己變成自己的slave(簡稱slaveof self)是會傳回+OK的,因為響應slaveof指令時,隻是設定下master,接下來的同步都是異步進行的。

slaveof self之後,發現redis仍然是可以服務的,但請求響應慢了很多,一個請求通常持續好幾秒鐘,為什麼會這樣?

step1. 當redis接收到slaveof後,将masterhost設定為自己,然後傳回OK。

step2. redis在背景建立到master的連接配接,這條連接配接的兩端都是這個redis自身,兩端分别稱為master、slave

step3. 連接配接建立後,slave調用syncWithMaster與master建立同步

step4. slave向master異步發送PING,master回複PONG

step5. slave向master同步發送REPLCONF,調用sendSynchronousCommand,這裡會阻塞的等待5s,直到逾時;而由于redis是單線程,此時請求發送給master(實際上是自己),而master又阻塞在這個請求上,是以最終導緻REPLCONF一定會逾時,slave日志裡會列印

step6. slave同步發送PSYNC指令給master,同樣因為自己正阻塞等待,最後這個請求也一定會逾時,日志裡會列印

step7. slave将讀事件處理handler設定為readSyncBulkPayload(6逾時,slave上認為沒有錯誤,個人覺得這裡的實作是有問題的),然後進入下一次事件循環,此時redis作為master收到了5、6裡自己發出的請求,回複了+OK;讀事件接下來會觸發slave執行readSyncBulkPayload,從master讀取rdb檔案的長度,而實際讀到的是+OK,于是認為協定錯了,就關閉了到master的連接配接,日志裡會列印

redis會不斷重複1-7的步驟,當接受到正常的請求時,如果redis剛好阻塞在同步發送REPLCONF、PSYNC(兩個逾時各5s,共10s)的過程中,則需要等待這些請求逾時,redis下一次進入事件循環才處理請求,是以使用者看到redis的請求延時很大(0-10s不等)。

slaveof self會使redis進入循環嘗試主備同步的狀态,對服務影響非常大,是以運維redis時千萬得小心。

繼續閱讀