基於zookeeper實現分布式配置中心(一)


  

  最近在學習zookeeper,發現zk真的是一個優秀的中間件。在分布式環境下,可以高效解決數據管理問題。在學習的過程中,要深入zk的工作原理,並根據其特性做一些簡單的分布式環境下數據管理工具。本文首先對zk的工作原理和相關概念做一下介紹,然后帶大家做一個簡單的分布式配置中心。

zookeeper介紹

  zookeeper是一個分布式協調框架,主要是解決分布式應用中經常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集群管理、分布式應用配置項的管理、分布式鎖等。

zookeeper使用

查看節點

  # ls /path

創建節點

  #create /path data

修改節點

  #set /path data

刪除節點

  #delete /path

獲取節點數據

  #get /path

zookeeper C/S連接狀態

  1)KeeperState.Expired:客戶端和服務器在ticktime的時間周期內,是要發送心跳通知的。這是租約協議的一個實現。客戶端發送request,告訴服務器其上一個租約時間,服務器收到這個請求后,告訴客戶端其下一個租約時間是哪個時間點。當客戶端時間戳達到最后一個租約時間,而沒有收到服務器發來的任何新租約時間,即認為自己下線(此后客戶端會廢棄這次連接,並試圖重新建立連接)。這個過期狀態就是Expired狀態

  2)KeeperState.Disconnected:就像上面那個狀態所述,當客戶端斷開一個連接(可能是租約期滿,也可能是客戶端主動斷開)這是客戶端和服務器的連接就是Disconnected狀態

  3)KeeperState.SyncConnected:一旦客戶端和服務器的某一個節點建立連接(注意,雖然集群有多個節點,但是客戶端一次連接到一個節點就行了),並完成一次version、zxid的同步,這時的客戶端和服務器的連接狀態就是SyncConnected

  4)KeeperState.AuthFailed:ookeeper客戶端進行連接認證失敗時,發生該狀態

zookeeper工作原理

  文件系統 + 監聽機制

文件系統特點

  同一個目錄下文件名稱不能重復,同樣zookeeper也是這樣的,zookeeper中統一叫作znode。znode節點可以包含子znode,也可以同時包含數據。znode只適合存儲非常小的數據,不能超過1M,最好都小於1K。

znode節點類型

  臨時節點(EPHEMERAL):客戶端關閉zk連接后清除

  永久節點(persistent):持久化節點,除非客戶端主動刪除

  有編號節點(Persistent_sequential):自動增加順序編號的znode持久化節點

  臨時有編號(Ephemral_ sequential):臨時自動編號設置,znode節點編號會自動增加,但是會客戶端連接斷開而消失。分布式鎖用的是這個類型的節點。

  注:EPHEMERAL 臨時類型的節點不能有子節點,對於zk來說,有幾個節點數據就會存儲幾份。

監聽機制

  客戶端注冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、節點刪除、子目錄節 點增加刪除)時,zookeeper會通知客戶端。

  

  1、客戶端啟動時向zookeeper服務器注冊信息

  2、客戶端啟動同時注冊一系列的Watcher類型的監聽器到本地的WatchManager中

  3、zookeeper服務器中節點發生變化后,觸發watcher事件后通知給客戶端,客戶端線程從WatcherManager中取出對應的Watcher對象來執行回調邏輯。

zookeeper監聽的事件類型

  EventType.NodeCreated:當znode節點被創建時,該事件被觸發。

  EventType.NodeChildrenChanged:當znode節點的直接子節點被創建、被刪除、子節點數據發生變更時,該事件被觸發。

  EventType.NodeDataChanged:當znode節點的數據發生變更時,該事件被觸發。

  EventType.NodeDeleted:當znode節點被刪除時,該事件被觸發。

  EventType.None:當zookeeper客戶端的連接狀態發生變更時,即KeeperState.Expired、KeeperState.Disconnected、KeeperState.SyncConnected、KeeperState.AuthFailed狀態切換時,描述的事件類型為EventType.None。

zookeeper下server工作狀態

  LOOKING:當前server不知道leader是誰,正在選舉

  LEADING:當前server即為選舉出來的leader

  FOLLOWING:leader已經選舉出來,當前server是follower

 ZAB協議

  ZAB 協議全稱:Zookeeper Atomic Broadcast(Zookeeper 原子廣播協議)。
  ZAB 協議作用:解決分布式數據管理一致性。
  ZAB 協議定義:ZAB 協議是為分布式協調服務 Zookeeper 專門設計的一種支持 崩潰恢復 和 消息廣播 協議。
  基於該協議,Zookeeper 實現了一種 主備模式 的系統架構來保持集群中各個副本之間數據一致性。

消息廣播

  zookeeper集群采用主從(leader-follower)模式保證服務高可用。leader節點可讀可寫,follower節點只讀,這種模式就需要保證leader節點和follower節點的數據一致性。對於客戶端發送的寫請求,全部由 Leader 接收,Leader 將請求封裝成一個事務 Proposal,將其發送給所有 Follwer ,然后,根據所有 Follwer 的反饋,如果超過半數成功響應,則執行 commit 操作(先提交自己,再發送 commit 給所有 Follwer)。

  注:上述中有一個概念:兩階段提交過程(分布式系統中數據一致性經常會涉及到的方案)。follower節點是可以處理寫請求的,會轉發給leader節點。leader節點通過消息廣播(二階段提交)同步寫操作到follower節點,保證數據一致性。

  zookeeper中每個事務都對應一個ZXID(全局的、唯一的、順序的)。ZXID 是一個 64 位的數字,其中低 32 位可以看作是一個簡單的遞增的計數器,針對客戶端的每一個事務請求,Leader 都會產生一個新的事務 Proposal 並對該計數器進行 + 1 操作。而高 32 位則代表了 Leader 服務器上取出本地日志中最大事務 Proposal 的 ZXID,並從該 ZXID 中解析出對應的 epoch 值,然后再對這個值加一。

崩潰恢復

  即如果在消息廣播的過程中,leader死掉了,如何保證數據的一致性問題。

  假設兩種異常情況:
  1、一個事務在 Leader 上提交了,並且過半的 Folower 都響應 Ack 了,但是 Leader 在 Commit 消息發出之前掛了。
  2、假設一個事務在 Leader 提出之后,Leader 掛了。

  考慮到上述兩種異常情況,Zab 協議崩潰恢復要求滿足以下兩個要求:
  1)確保已經被 Leader 提交的 Proposal 必須最終被所有的 Follower 服務器提交。
  2)確保丟棄已經被 Leader 提出的但是沒有被提交的 Proposal。

  崩潰恢復主要包含:leader選舉 和 數據恢復。

  leader選舉:

  1、要求 可用節點數量 > 總節點數量/2  。注意 是 > , 不是 ≥。

     2、新選舉出來的 Leader 不能包含未提交的 Proposal(新選舉的 Leader 必須都是已經提交了 Proposal 的 Follower 服務器節點) 、新選舉的 Leader 節點中含有最大的 zxid(可以避免 Leader 服務器檢查 Proposal 的提交和丟棄工作。如果zxid相同,選擇server_id【zoo.cfg中的myid】最大的。)

  數據恢復

  1、上面講過了ZXID的高 32 位代表了每代 Leader 的唯一性,低 32 代表了每代 Leader 中事務的唯一性。同時,也能讓 Follwer 通過高 32 位識別不同的 Leader。簡化了數據恢復流程。

  2、基於這樣的策略:當 Follower 鏈接上 Leader 之后,Leader 服務器會根據自己服務器上最后被提交的 ZXID 和 Follower 上的 ZXID 進行比對,比對結果要么回滾,要么和 Leader 同步。

zookeeper集群腦裂

  集群的腦裂通常是發生在節點之間通信不可達的情況下,集群會分裂成不同的小集群,小集群各自選出自己的master節點,導致原有的集群出現多個master節點的情況。

zookeeper集群節點數(奇數or偶數?)

  只要我們清楚集群leader選舉的要求(可用節點數量 > 總節點數量/2  。注意 是 > , 不是 ≥),我相信很容易明白奇數節點集群相比偶數節點的集群有更大的優勢。

  1、發生腦裂(分成2個小集群)的情況下,奇數節點的集群總會有一個小集群滿足可用節點數量 > 總節點數量/2,所以zookeeper集群總能選取出leader。

  2、在容錯能力相同的情況下,奇數集群更節省資源。還是要清楚leader選舉的要求哈,舉個列子:3個節點的集群,如果集群可以正常工作(即leader選舉成功),至少需要2個節點是正常的;4個節點的集群,如果集群可以正常工作(即leader選舉成功),至少需要3個節點是正常的。那么3個節點的集群和4個節點的集群都有一個節點宕機的容錯能力。很明顯,在容錯能力相同的情況下,奇數節點的集群更節省資源。

 zookeeper和eureka對比

  在分布式系統領域有個著名的 CAP定理(C- 數據一致性;A-服務可用性;P-服務對網絡分區故障的容錯性,這三個特性在任何分布式系統中不能同時滿足,最多同時滿足兩個)。

  zookeeper基於CP,即任何時刻對ZooKeeper的訪問請求能得到一致的數據結果,同時系統對網絡分割具備容錯性;但是它不能保證每次服務請求的可用性(注:也就 是在極端環境下,zookeeper可能會丟棄一些請求,消費者程序需要重新請求才能獲得結果)。至於zookeeper為啥不能保證服務的高可用,大家可以想一下發生腦裂后無法選取leader、選取leader過程中丟棄某些請求。當網絡出現故障時,剩余zk集群server會發起投票選舉新的leader,但是此過程會持續30~120s,此過程對於高並發來說十分漫長,會導致整個注冊服務的癱瘓,這是不可容忍的。 

  Eureka基於AP,不會有類似於ZooKeeper的選舉leader的過程,采用的是Peer to Peer 對等通信,沒有leader/follower的說法,每個peer都是對等的;客戶端請求會自動切換 到新的Eureka節點;當宕機的服務器重新恢復后,Eureka會再次將其納入到服務器集群管理之中。當Eureka節點接受客戶端請求時,所有的操作都會在節點間進行復制(replicate To Peer)操作,將請求復制到該 Eureka Server 當前所知的其它所有節點中。至於為啥Eureka不能保證數據一致性,源於Eureka的自我保護機制:如果在15分鍾內超過85%的節點都沒有正常的心跳,那么Eureka就認為客戶端與注冊中心出現了網絡故障,此時會出現以下幾種情況: 

  1. Eureka不再從注冊列表中移除因為長時間沒收到心跳而應該過期的服務 。

  2. Eureka仍然能夠接受新服務的注冊和查詢請求,但是不會被同步到其它節點上(即保證當前節點依然可用) 。

  3. 當網絡穩定時,當前實例新的注冊信息會被同步到其它節點中。

  因此, Eureka可以很好的應對因網絡故障導致部分節點失去聯系的情況,而不會像zookeeper那樣使整個注冊服務癱瘓。

總結

  以上是對zookeeper的工作原理和相關概念的一些整理,希望能對大家認識zookeeper有所幫助。下一篇文章開始基於zookeeper做一個簡單的分布式配置中心,敬請期待!!!

參考鏈接

  https://blog.csdn.net/pml18710973036/article/details/64121522

  https://www.cnblogs.com/stateis0/p/9062133.html

  https://www.jianshu.com/p/2bceacd60b8a

  

  

 


免責聲明!

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



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