ZooKeeper常見問題


轉載自原文:zookeeper(二)常見問題匯總

一、為什么zookeeper要部署基數台服務器?

所謂的zookeeper容錯是指,當宕掉幾個zookeeper服務器之后,剩下的個數必須大於宕掉的個數,也就是剩下的服務數必須大於n/2,zookeeper才可以繼續使用,無論奇偶數都可以選舉leader。5台機器最多宕掉2台,還可以繼續使用,因為剩下3台大於5/2。說為什么最好為奇數個,是在以最大容錯服務器個數的條件下,會節省資源,比如,最大容錯為2的情況下,對應的zookeeper服務數,奇數為5,而偶數為6,也就是6個zookeeper服務的情況下最多能宕掉2個服務,所以從節約資源的角度看,沒必要部署6(偶數)個zookeeper服務。

zookeeper有這樣一個特性:集群中只要有過半的機器是正常工作的,那么整個集群對外就是可用的。也就是說如果有2個zookeeper,那么只要有1個死了zookeeper就不能用了,因為1沒有過半,所以2個zookeeper的死亡容忍度為0;同理,要是有3個zookeeper,一個死了,還剩下2個正常的,過半了,所以3個zookeeper的容忍度為1;同理你多列舉幾個:2->0;3->1;4->1;5->2;6->2會發現一個規律,2n和2n-1的容忍度是一樣的,都是n-1,所以為了更加高效,何必增加那一個不必要的zookeeper呢。

根據以上可以得出結論:出現資源節省的角度

二、zookeeper腦裂(Split-Brain)問題

2.1、什么是腦裂?

白話點說,就是比如當你的 cluster 里面有兩個結點,它們都知道在這個 cluster 里需要選舉出一個 master。那么當它們兩之間的通信完全沒有問題的時候,就會達成共識,選出其中一個作為 master。但是如果它們之間的通信出了問題,那么兩個結點都會覺得現在沒有 master,所以每個都把自己選舉成 master。於是 cluster 里面就會有兩個 master。

對於Zookeeper來說有一個很重要的問題,就是到底是根據一個什么樣的情況來判斷一個節點死亡down掉了。 在分布式系統中這些都是由監控者來判斷的,但是監控者也很難判定其他節點的狀態,唯一 一個可靠的途徑就是心跳,Zookeeper也是使用心跳來判斷客戶端是否仍然活着。

使用ZooKeeper來做master HA基本都是同樣的方式,每個節點都嘗試注冊一個象征master的臨時節點;其他沒有注冊成功的則成為slaver,並且通過watch機制監控着master所創建的臨時節點,Zookeeper通過內部心跳機制來確定master的狀態,一旦master出現意外Zookeeper能很快獲悉並且通知其他的slaver,其他slaver在之后作出相關反應。這樣就完成了一個切換。這種模式也是比較通用的模式,基本大部分都是這樣實現的,但是這里面有個很嚴重的問題,如果注意不到會導致短暫的時間內系統出現腦裂,因為心跳出現超時可能是master掛了,但是也可能是master,zookeeper之間網絡出現了問題,也同樣可能導致。這種情況就是假死,master並未死掉,但是與ZooKeeper中其他機器之間的網絡出現問題導致其他節點認為其掛掉了然后進行新的Leader選舉切換,這樣slaver中就有一個成為了master,但是原本的master並未死掉,這時候client也獲得master切換的消息,但是仍然會有一些延時,zookeeper需要一個一個通知,這時候整個系統就很混亂可能有一部分client已經通知到了連接到新的master上去了,有的client仍然連接在老的master上如果同時有兩個client需要對master的同一個數據更新並且剛好這兩個client此刻分別連接在新老的master上,就會出現很嚴重問題。

總結:

假死:由於心跳超時(網絡原因導致的)認為master死了,但其實master還存活着。
腦裂:由於假死會發起新的master選舉,選舉出一個新的master,但舊的master網絡又通了,導致出現了兩個master ,有的客戶端連接到老的master 有的客戶端鏈接到新的master。

2.2、什么原因導致的?

要解決Split-Brain的問題,一般有3種方式:

  • Quorums(法定人數),比如3個節點的集群,Quorums = 2, 也就是說集群可以容忍1個節點失效,這時候還能選舉出1個leader,集群還可用。比如4個節點的集群,它的Quorums = 3,Quorums要超過3,相當於集群的容忍度還是1,如果2個節點失效,那么整個集群還是無效的
  • 采用Redundant communications,冗余通信的方式,集群中采用多種通信方式,防止一種通信方式失效導致集群中的節點無法通信。
  • Fencing, 共享資源的方式,比如能看到共享資源就表示在集群中,能夠獲得共享資源的鎖的就是Leader,看不到共享資源的,就不在集群中。

ZooKeeper采用了Quorums這種方式,即只有集群中超過半數節點投票才能選舉出Leader。這樣的方式可以確保leader的唯一性,要么選出唯一的一個leader,要么選舉失敗。在ZooKeeper中Quorums有2個作用:

  • 集群中最少的節點數用來選舉Leader保證集群可用
  • 通知客戶端數據已經安全保存前集群中最少數量的節點數已經保存了該數據。一旦這些節點保存了該數據,客戶端將被通知已經安全保存了,可以繼續其他任務。而集群中剩余的節點將會最終也保存了該數據

假設某個leader假死,其余的followers選舉出了一個新的leader。這時,舊的leader復活並且仍然認為自己是leader,這個時候它向其他followers發出寫請求也是會被拒絕的。因為每當新leader產生時,會生成一個epoch,這個epoch是遞增的,followers如果確認了新的leader存在,知道其epoch,就會拒絕epoch小於現任leader epoch的所有請求。那有沒有follower不知道新的leader存在呢,有可能,但肯定不是大多數,否則新leader無法產生。Zookeeper的寫也遵循quorum機制,因此,得不到大多數支持的寫是無效的,舊leader即使各種認為自己是leader,依然沒有什么作用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM