我們一起搞定Redis腦裂問(wèn)題
Redis 腦裂問(wèn)題是指,在 Redis 哨兵模式或集群模式中,由于網(wǎng)絡(luò)原因,導(dǎo)致主節(jié)點(diǎn)(Master)與哨兵(Sentinel)和從節(jié)點(diǎn)(Slave)的通訊中斷,此時(shí)哨兵就會(huì)誤以為主節(jié)點(diǎn)已宕機(jī),就會(huì)在從節(jié)點(diǎn)中選舉出一個(gè)新的主節(jié)點(diǎn),此時(shí) Redis 的集群中就出現(xiàn)了兩個(gè)主節(jié)點(diǎn)的問(wèn)題,就是 Redis 腦裂問(wèn)題。
腦裂問(wèn)題影響
Redis 腦裂問(wèn)題會(huì)導(dǎo)致數(shù)據(jù)丟失,為什么呢?來(lái)看腦裂問(wèn)題產(chǎn)生的過(guò)程:
圖片
而最后一步,當(dāng)舊的 Master 變?yōu)?Slave 之后,它的執(zhí)行流程如下:
- Slave(舊 Master)會(huì)向 Master(新)申請(qǐng)全量數(shù)據(jù)。
- Master 會(huì)通過(guò) bgsave 的方式生成當(dāng)前 RDB 快照,并將 RDB 發(fā)送給 Slave。
- Slave 拿到 RDB 之后,先進(jìn)行 flush 清空當(dāng)前數(shù)據(jù)(此時(shí)第四步舊客戶端給他的發(fā)送的數(shù)據(jù)就丟失了)。
- 之后再加載 RDB 數(shù)據(jù),初始化自己當(dāng)前的數(shù)據(jù)。
從以上過(guò)程中可以看出,在執(zhí)行到第三步的時(shí)候,原客戶端在舊 Master 寫(xiě)入的數(shù)據(jù)就丟失了,這就是數(shù)據(jù)丟失的問(wèn)題。
如何解決腦裂問(wèn)題?
腦裂問(wèn)題只需要在舊 Master 恢復(fù)網(wǎng)絡(luò)之后,切換身份為 Slave 期間,不接收客戶端的數(shù)據(jù)寫(xiě)入即可,那怎么解決這個(gè)問(wèn)題呢?
Redis 為我們提供了以下兩個(gè)配置,通過(guò)以下兩個(gè)配置可以盡可能的避免數(shù)據(jù)丟失的問(wèn)題:
- min-slaves-to-write:與主節(jié)點(diǎn)通信的從節(jié)點(diǎn)數(shù)量必須大于等于該值主節(jié)點(diǎn),否則主節(jié)點(diǎn)拒絕寫(xiě)入。
- min-slaves-max-lag:主節(jié)點(diǎn)與從節(jié)點(diǎn)通信的 ACK 消息延遲必須小于該值,否則主節(jié)點(diǎn)拒絕寫(xiě)入。
這兩個(gè)配置項(xiàng)必須同時(shí)滿足,不然主節(jié)點(diǎn)拒絕寫(xiě)入。
在假故障期間滿足 min-slaves-to-write 和 min-slaves-max-lag 的要求,那么主節(jié)點(diǎn)就會(huì)被禁止寫(xiě)入,腦裂造成的數(shù)據(jù)丟失情況自然也就解決了。