Redis腦裂現(xiàn)象
什么是Redis的腦裂現(xiàn)象
當(dāng)Redis主從集群環(huán)境出現(xiàn)兩個主節(jié)點為客戶端提供服務(wù),這時客戶端請求命令可能會發(fā)生數(shù)據(jù)丟失的情況。
腦裂出現(xiàn)的場景
場景一
主從哨兵集群中如果當(dāng)發(fā)生主從集群切換時,那么一定是超過預(yù)設(shè)quorum數(shù)量的哨兵和主庫連接超時了,這時哨兵集群才會將主庫判斷為主觀下線,然后哨兵開始選舉新的主節(jié)點,進行故障轉(zhuǎn)移,轉(zhuǎn)移完畢后客戶端和新的主節(jié)點通信恢復(fù)正常請求。
如果在哨兵進行選舉,故障轉(zhuǎn)移的過程中原主節(jié)點恢復(fù)和客戶端的通信,那么證明原主節(jié)點沒有真正的故障,這時客戶端依舊可以向原主節(jié)點正常通信,這就是腦裂產(chǎn)生的第一個場景,示意圖如下
假故障:
1、同服務(wù)器其它進程占用大量CPU資源,導(dǎo)致主節(jié)點短時間無法響應(yīng)心跳,CPU資源空閑后恢復(fù)正常。
2、主庫自身阻塞,如處理bigkey或者發(fā)生內(nèi)存swap時,短時間無法響應(yīng)心跳,阻塞解決后心跳恢復(fù)正常。
真故障:
1、服務(wù)器宕機。
2、實例進程掛了。
場景二
網(wǎng)絡(luò)分區(qū),主節(jié)點和客戶端,哨兵和從庫分割為了兩個網(wǎng)絡(luò),主庫和客戶端處在一個網(wǎng)絡(luò)中,從庫和哨兵在另外一個網(wǎng)絡(luò)中,此時哨兵也會發(fā)起主從切換,出現(xiàn)兩個主節(jié)點的情況。
腦裂帶來的影響
腦裂出現(xiàn)后帶來最嚴(yán)重的后果就是數(shù)據(jù)丟失,為什么會出現(xiàn)數(shù)據(jù)丟失的問題呢,主要原因是新主庫確定后會向所有的實例發(fā)送slave of命令,讓所有實例重新進行全量同步,而全量同步首先就會將實例上的數(shù)據(jù)先清空,所以在主從同步期間在原主庫執(zhí)行的命令將會被清空(上面場景二是同樣的道理,在網(wǎng)絡(luò)分區(qū)恢復(fù)后原主節(jié)點將被降級為從節(jié)點,并且執(zhí)行全量同步導(dǎo)致數(shù)據(jù)丟失),所以這就是數(shù)據(jù)丟失的具體原因。
如何應(yīng)對腦裂
腦裂的主要原因其實就是哨兵集群認為主節(jié)點已經(jīng)出現(xiàn)故障了,重新選舉其它從節(jié)點作為主節(jié)點,而原主節(jié)點其實是假故障,從而導(dǎo)致短暫的出現(xiàn)兩個主節(jié)點,那么在主從切換期間客戶端一旦給原主節(jié)點發(fā)送命令,就會造成數(shù)據(jù)丟失。
所以應(yīng)對腦裂的解決辦法應(yīng)該是去限制原主庫接收請求,Redis提供了兩個配置項。
- min-slaves-to-write:與主節(jié)點通信的從節(jié)點數(shù)量必須大于等于該值主節(jié)點,否則主節(jié)點拒絕寫入。
- min-slaves-max-lag:主節(jié)點與從節(jié)點通信的ACK消息延遲必須小于該值,否則主節(jié)點拒絕寫入。
這兩個配置項必須同時滿足,不然主節(jié)點拒絕寫入。
在假故障期間滿足min-slaves-to-write和min-slaves-max-lag的要求,那么主節(jié)點就會被禁止寫入,腦裂造成的數(shù)據(jù)丟失情況自然也就解決了。
腦裂可以完全解決嗎
通過上面的學(xué)習(xí)我們知道了腦裂出現(xiàn)的場景,帶來的問題,以及解決辦法,那么腦裂問題可以完全被解決嗎?我們直接看下面的場景
為了防止腦裂我們將min-slaves-to-write設(shè)置為1,min-slaves-max-lag設(shè)置為12s,down-after-milliseconds哨兵判斷主節(jié)點客觀下線的限制為10s,主節(jié)點因為某些原因卡住了15s,導(dǎo)致哨兵集群判斷主節(jié)點為主觀下線,主從切換,因為沒有一個從節(jié)點與主節(jié)點之間的數(shù)據(jù)復(fù)制在12s內(nèi),這樣就規(guī)避腦裂的情況。
但是我們再看另外一個場景
我們同樣將min-slaves-to-write設(shè)置為1,min-slaves-max-lag 設(shè)置為 15s,down-after-milliseconds哨兵判斷主節(jié)點客觀下線的限制為10s,哨兵主從切換需要 5s。主節(jié)點因為某些原因卡住了 12s,這時還會發(fā)生腦裂嗎?
主節(jié)點卡住12s這時哨兵集群判斷主節(jié)點下線,同時哨兵集群做主從切換需要5s,這就意味著主從切換過程中,主節(jié)點恢復(fù)運行,而min-slaves-max-lag設(shè)置為15s那么主節(jié)點還是可寫,也就是說在12s~15s這期間如果有客戶端寫入原主節(jié)點,那么這段時間的數(shù)據(jù)會丟失。
總結(jié)
Redis腦裂可以采用min-slaves-to-write和min-slaves-max-lag合理配置盡量規(guī)避,但無法徹底解決,Redis腦裂最本質(zhì)的問題是主從集群內(nèi)部沒有共識算法來維護多個節(jié)點的強一致性,它不像Zookeeper那樣,每次寫入必須大多數(shù)節(jié)點成功后才算成功,當(dāng)腦裂發(fā)生時,Zookeeper節(jié)點被孤立,此時無法寫入大多數(shù)節(jié)點,寫請求會直接失敗,因此Zookeeper才能保證集群的強一致性。