1. 程式人生 > >Zookeeper已經分散式環境中的假死腦裂

Zookeeper已經分散式環境中的假死腦裂

Zookeeper簡介

在上班之前都不知道有這樣一個東西,在開始說假死腦裂之前先說說Zookeeper吧。

Zookeeper
zookeeper是一個分散式應用程式的協調服務。它是一個為分散式應用提供一致性服務的軟體,提供的效能包括:配置維護、名字服務、分散式同步、組服務等。
zookeeper是以Fast Paxos演算法為基礎,paxos演算法存在活鎖的問題,即當有多個proposer交錯提交時,有可能互相排斥導致沒有一個proposer能提交成功,而Fase Paxos作了一些優化,通過選舉產生一個leader,只有leader才能提交proposer,具體的可以看一下Fast Paxos演算法。

Zookeeper的基本運轉流程:

  1. 選舉leader;
  2. 同步資料;
  3. 選舉leader過程中演算法有很多,但要達到的選舉標準是一致的;
  4. leader要有更高的zxid;
  5. 叢集中大多數的機器得到響應並follow選出的leader。

小說了一下Zookeeper,接下來討論一下腦裂,假死等等問題以及解決方法吧。

假死腦裂
在一個大的叢集中往往會有一個master的存在,在長期執行過程中不可避免會出現宕機等等的問題導致master不可用,在出現這樣的情況以後往往會對系統產生很大的影響,所以一般的分散式叢集中的master都採用了高可用的解決方案來避免這樣的情況發生。
master-slaver方式,存在一個master的節點,平時對外服務,同時有一個slaver節點來監控master,監控的同時有某種方式來進行資料同步。假如現在master掛掉了,slaver能很快獲知並且迅速切換為新的master。但是在這種方式中,監控切換是一個很大的難題,但是現在Zookeeper的watch和分散式鎖機制能比較好的解決這個問題。雖然Zookeeper很好的解決了這個問題,但是它的使用也存在其他的問題,比如腦裂。
導致腦裂的一個根源問題就是假死。

什麼叫假死呢?
有一個很重要的問題,就是到底是根據一個什麼樣的情況來判斷一個節點死亡down掉了。
在分散式系統中這些都是有監控者來判斷的,但是監控者也很難判定其他的節點的狀態,唯一一個可靠的途徑就是心跳,包括Zookeeper也是使用心跳來判斷客戶端是否仍然活著。
使用ZooKeeper來做master HA基本都是同樣的方式,每個節點都嘗試註冊一個象徵master的臨時節點其他沒有註冊成功的則成為slaver,並且通過watch機制監控著master所建立的臨時節點,Zookeeper通過內部心跳機制來確定master的狀態,一旦master出現意外Zookeeper能很快獲悉並且通知其他的slaver,其他slaver在之後作出相關反應。這樣就完成了一個切換。這種模式也是比較通用的模式,基本大部分都是這樣實現的,但是這裡面有個很嚴重的問題,如果注意不到會導致短暫的時間內系統出現腦裂,因為心跳出現超時可能是master掛了,但是也可能是master,zookeeper之間網路出現了問題,也同樣可能導致。這種情況就是假死,master並未死掉,但是與ZooKeeper之間的網路出現問題導致Zookeeper認為其掛掉瞭然後通知其他節點進行切換,這樣slaver中就有一個成為了master,但是原本的master並未死掉,這時候client也獲得master切換的訊息,但是仍然會有一些延時,zookeeper需要通訊需要一個一個通知,這時候整個系統就很混亂可能有一部分client已經通知到了連線到新的master上去了,有的client仍然連線在老的master上如果同時有兩個client需要對master的同一個資料更新並且剛好這兩個client此刻分別連線在新老的master上,就會出現很嚴重問題。

是什麼原因導致這樣情況的出現呢?
主要原因是Zookeeper叢集和Zookeeper client判斷超時並不能做到完全同步,也就是說可能一前一後,如果是叢集先於client發現那就會出現上面的情況。同時,在發現並切換後通知各個客戶端也有先後快慢。一般出現這種情況的機率很小,需要master與Zookeeper叢集網路斷開但是與其他叢集角色之間的網路沒有問題,還要滿足上面那些情況,但是一旦出現就會引起很嚴重的後果,資料不一致。

如何避免?
在slaver切換的時候不在檢查到老的master出現問題後馬上切換,而是在休眠一段足夠的時間,確保老的master已經獲知變更並且做了相關的shutdown清理工作了然後再註冊成為master就能避免這類問題了,這個休眠時間一般定義為與Zookeeper定義的超時時間就夠了,但是這段時間內系統不可用了。