腦裂真的是一個很頭疼的問題(ps: 腦殼都裂開了,能不疼嗎?),看下面的圖:html
1、哨兵(sentinel)模式下的腦裂redis
![](http://static.javashuo.com/static/loading.gif)
如上圖,1個master與3個slave組成的哨兵模式(哨兵獨立部署於其它機器),剛開始時,2個應用服務器server一、server2都鏈接在master上,若是master與slave及哨兵之間的網絡發生故障,可是哨兵與slave之間通信正常,這時3個slave其中1個通過哨兵投票後,提高爲新master,若是剛好此時server1仍然鏈接的是舊的master,而server2鏈接到了新的master上。數據庫
數據就不一致了,基於setNX指令的分佈式鎖,可能會拿到相同的鎖;基於incr生成的全局惟一id,也可能出現重複。服務器
2、集羣(cluster)模式下的腦裂網絡
![](http://static.javashuo.com/static/loading.gif)
custer模式下,這種狀況要更復雜,見上面的示意圖,集羣中有6組分片,每給分片節點都有1主1從,若是出現網絡分區時,各類節點之間的分區組合都有可能,上面列了2種狀況:分佈式
狀況A:3d
假設master1與slave4落到同1個分區,這時slave4通過選舉後,可能會被提高爲新的master4,而另外一個分區裏的slave1,可能會提高爲新的master1。看過本博客前面介紹redis cluster的同窗應該知道,cluster中key的定位是依賴slot(槽位),狀況A通過這一翻折騰後,master1與master4上的slot,出現了重複,在二個分區裏都有。相似的,若是依賴incr及setNX的應用場景,都會出現數據不一致的狀況。server
狀況B:htm
若是每給分片內部的邏輯(即:主從關係)沒有亂,只是剛好分紅二半,這時slot總體上看並無出現重複,若是原來請求的key落在其它區,最多隻是訪問不到,還不致於發生數據不一致的狀況。(即:寧肯出錯,也不要出現數據混亂)blog
3、主從遷移帶來的不一致
![](http://static.javashuo.com/static/loading.gif)
如上圖,1主1從,若是採用incr來生成全局惟一鍵,假如master上的值是4,可是還沒有同步到slave上(slave上仍然是舊值3),這時候若是發生選舉,slave被提高爲新master,應用服務器server1切換到新主後,下次再incr獲取的值,就可能重複了(3+1=4)
總結:雖然上面的狀況都比較極端,但實際中仍是有可能發生的,正如官方文檔所言,redis並不能保證強一致性(Redis Cluster is not able to guarantee strong consistency. / In general Redis + Sentinel as a whole are a an eventually consistent system) 對於要求強一致性的應用,更應該傾向於相信RDBMS(傳統關係型數據庫)。
參考: