Redis 腦裂問題是指,在 Redis 哨兵模式或集羣模式中,由於網絡原因,導致主節點(Master)與哨兵(Sentinel)和從節點(Slave)的通訊中斷,此時哨兵就會誤以爲主節點已宕機,就會在從節點中選舉出一個新的主節點,此時 Redis 的集羣中就出現了兩個主節點的問題,就是 Redis 腦裂問題。
腦裂問題影響
Redis 腦裂問題會導致數據丟失,爲什麼呢?來看腦裂問題產生的過程:
而最後一步,當舊的 Master 變爲 Slave 之後,它的執行流程如下:
- Slave(舊 Master)會向 Master(新)申請全量數據。
- Master 會通過 bgsave 的方式生成當前 RDB 快照,並將 RDB 發送給 Slave。
- Slave 拿到 RDB 之後,先進行 flush 清空當前數據(此時第四步舊客戶端給他的發送的數據就丟失了)。
- 之後再加載 RDB 數據,初始化自己當前的數據。
從以上過程中可以看出,在執行到第三步的時候,原客戶端在舊 Master 寫入的數據就丟失了,這就是數據丟失的問題。
如何解決腦裂問題?
腦裂問題只需要在舊 Master 恢復網絡之後,切換身份爲 Slave 期間,不接收客戶端的數據寫入即可,那怎麼解決這個問題呢?
Redis 爲我們提供了以下兩個配置,通過以下兩個配置可以儘可能的避免數據丟失的問題:
- min-slaves-to-write:與主節點通信的從節點數量必須大於等於該值主節點,否則主節點拒絕寫入。
- min-slaves-max-lag:主節點與從節點通信的 ACK 消息延遲必須小於該值,否則主節點拒絕寫入。
這兩個配置項必須同時滿足,不然主節點拒絕寫入。
在假故障期間滿足 min-slaves-to-write 和 min-slaves-max-lag 的要求,那麼主節點就會被禁止寫入,腦裂造成的數據丟失情況自然也就解決了。
課後思考
設置了參數之後,Redis 腦裂問題能完全被解決嗎?爲什麼?Zookeeper 有腦裂問題嗎?它是如何解決腦裂問題的?
本文已收錄到我的面試小站 www.javacn.site,其中包含的內容有:Redis、JVM、併發、併發、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、設計模式、消息隊列等模塊。