腦裂(split-brain)就是「大腦分裂」,也就是原本一個「大腦」被拆分了兩個或多個「大腦」,咱們都知道,若是一我的有多個大腦,而且相互獨立的話,那麼會致使人體「手舞足蹈」,「不聽使喚」。java
腦裂一般會出如今集羣環境中,好比ElasticSearch、Zookeeper集羣,而這些集羣環境有一個統一的特色,就是它們有一個大腦,好比ElasticSearch集羣中有Master節點,Zookeeper集羣中有Leader節點。算法
本篇文章着重來給你們講一下Zookeeper中的腦裂問題,以及是若是解決腦裂問題的。服務器
對於一個集羣,想要提升這個集羣的可用性,一般會採用多機房部署,好比如今有一個由6臺zkServer所組成的一個集羣,部署在了兩個機房: 微信
正常狀況下,此集羣只會有一個Leader,那麼若是機房之間的網絡斷了以後,兩個機房內的zkServer仍是能夠相互通訊的,若是不考慮過半機制,那麼就會出現每一個機房內部都將選出一個Leader。 網絡
這就至關於本來一個集羣,被分紅了兩個集羣,出現了兩個「大腦」,這就是腦裂。學習
對於這種狀況,咱們也能夠看出來,本來應該是統一的一個集羣對外提供服務的,如今變成了兩個集羣同時對外提供服務,若是過了一會,斷了的網絡忽然聯通了,那麼此時就會出現問題了,兩個集羣剛剛都對外提供服務了,數據該怎麼合併,數據衝突怎麼解決等等問題。this
剛剛在說明腦裂場景時,有一個前提條件就是沒有考慮過半機制,因此實際上Zookeeper集羣中是不會出現腦裂問題的,而不會出現的緣由就跟過半機制有關。spa
在領導者選舉的過程當中,若是某臺zkServer得到了超過半數的選票,則此zkServer就能夠成爲Leader了。code
過半機制的源碼實現其實很是簡單:cdn
public class QuorumMaj implements QuorumVerifier {
private static final Logger LOG = LoggerFactory.getLogger(QuorumMaj.class);
int half;
// n表示集羣中zkServer的個數(準確的說是參與者的個數,參與者不包括觀察者節點)
public QuorumMaj(int n){
this.half = n/2;
}
// 驗證是否符合過半機制
public boolean containsQuorum(Set<Long> set){
// half是在構造方法裏賦值的
// set.size()表示某臺zkServer得到的票數
return (set.size() > half);
}
}
複製代碼
你們仔細看一下上面方法中的註釋,核心代碼就是下面兩行:
this.half = n/2;
return (set.size() > half);
複製代碼
舉個簡單的例子: 若是如今集羣中有5臺zkServer,那麼half=5/2=2,那麼也就是說,領導者選舉的過程當中至少要有三臺zkServer投了同一個zkServer,纔會符合過半機制,才能選出來一個Leader。
那麼有一個問題咱們想一下,選舉的過程當中爲何必定要有一個過半機制驗證? 由於這樣不須要等待全部zkServer都投了同一個zkServer就能夠選舉出來一個Leader了,這樣比較快,因此叫快速領導者選舉算法唄。
那麼再來想一個問題,過半機制中爲何是大於,而不是大於等於呢?
這就是更腦裂問題有關係了,好比回到上文出現腦裂問題的場景:
當機房中間的網絡斷掉以後,機房1內的三臺服務器會進行領導者選舉,可是此時過半機制的條件是set.size() > 3,也就是說至少要4臺zkServer才能選出來一個Leader,因此對於機房1來講它不能選出一個Leader,一樣機房2也不能選出一個Leader,這種狀況下整個集羣當機房間的網絡斷掉後,整個集羣將沒有Leader。
而若是過半機制的條件是set.size() >= 3,那麼機房1和機房2都會選出一個Leader,這樣就出現了腦裂。因此咱們就知道了,爲何過半機制中是大於,而不是大於等於。就是爲了防止腦裂。
若是假設咱們如今只有5臺機器,也部署在兩個機房:
此時過半機制的條件是set.size() > 2,也就是至少要3臺服務器才能選出一個Leader,此時機房件的網絡斷開了,對於機房1來講是沒有影響的,Leader依然仍是Leader,對於機房2來講是選不出來Leader的,此時整個集羣中只有一個Leader。
因此,咱們能夠總結得出,有了過半機制,對於一個Zookeeper集羣,要麼沒有Leader,要沒只有1個Leader,這樣就避免了腦裂問題。
有痛點纔有創新,一個技術確定都是爲了解決某個痛點纔出現的。 請幫忙轉發一下,若是想第一時間學習更多的精彩的內容,請關注微信公衆號:1點25