redis嘛,主要問題就是關乎數據的問題;分布式嘛,主要問題就是C(一致性)A(可用性)P(分區容錯性)。
在這里考慮兩個問題:數據不一致,數據丟失。
數據不一致:
有時候master會掛那么十幾秒鍾或者幾秒鍾然后又恢復正常,然后redis的調用者就覺得redis的master是沒問題的,他就接着使用這玩意,但是哨兵在這段時間內已經把這個master淘汰出去,不但如此還選了一個新的master供redis集群內部共享數據。這樣子就帶來了一個問題,新的master會很自以為是的同步它的數據給他的slave,但是redis的調用者並不向這個新的master發送任何數據,也就是他的數據壓根就不更新,導致他的slave數據也無法更新,最后實際對外提供服務的是那個被哨兵淘汰的master。
這就是傳說中的redis腦裂倘若集群部署的相對完善的話,新選舉的master還應向被哨兵淘汰的master同步數據,並且將被哨兵淘汰的master置為新master的一個slave,那就更有意思了,master在被淘汰之前還在工作,也就是還在接收數據並且試圖將數據寫入自己的緩存中,直到新的master開始向它同步數據,為了同步數據,舊的master會將自己的數據同步成新的master一樣,帶來的問題就是舊的master數據丟失。當主從節點間數據同步時間間隔設置的比較久的話就會使問題變得很嚴重。但是顯而易見的,像這樣的數據丟失問題是沒有辦法避免,只能減小數據同步時間間隔,以求減小數據丟失的數據量。
腦裂:
解決方法:
min-slaves-to-write 1
min-slaves-max-lag 10
說明:
要求至少有1個slave,數據復制和同步的延遲不能超過10秒
如果說一旦所有的slave,數據復制和同步的延遲都超過了10秒鍾,那么這個時候,master就不會再接收任何請求了
上面兩個配置可以減少異步復制和腦裂導致的數據丟失
減少異步復制的數據丟失
有了min-slaves-max-lag這個配置,就可以確保說,一旦slave復制數據和ack延時太長,就認為可能master宕機后損失的數據太多了,那么就拒絕寫請求,這樣可以把master宕機時由於部分數據未同步到slave導致的數據丟失降低的可控范圍內
減少腦裂的數據丟失
如果一個master出現了腦裂,跟其他slave丟了連接,那么上面兩個配置可以確保說,如果不能繼續給指定數量的slave發送數據,而且slave超過10秒沒有給自己ack消息,那么就直接拒絕客戶端的寫請求
這樣腦裂后的舊master就不會接受client的新數據,也就避免了數據丟失
上面的配置就確保了,如果跟任何一個slave丟了連接,在10秒后發現沒有slave給自己ack,那么就拒絕新的寫請求
因此在腦裂場景下,最多就丟失10秒的數據