什麼是ZooKeeper?

前言

只有光頭才能變強。

文本已收錄至個人GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3yhtml

上次寫了一篇 什麼是消息隊列?之後,原本想入門一下Kafka的(裝一下環境、看看Kafka一些概念啥的)。後來發現Kafka用到了ZooKeeper,而我又對ZooKeeper不瞭解,因此想先來學學什麼是ZooKeeper,再去看看什麼是Kafka。java

ZooKeeper相信你們已經聽過這個詞了,不知道你們對他了解多少呢?我第一次聽到ZooKeeper的時候是在學Eureka的時候(外行人都能看懂的SpringCloud,錯過了血虧!),一樣ZooKeeper也能夠做爲註冊中心node

後面聽到ZooKeeper的時候,是由於ZooKeeper能夠做爲分佈式鎖的一種實現。git

直至在瞭解Kafka的時候,發現Kafka也須要依賴ZooKeeper。Kafka使用ZooKeeper管理本身的元數據配置github

這篇文章來寫寫我學習ZooKeeper的筆記,若是有錯的地方但願你們能夠在評論區指出。數據結構

1、什麼是ZooKeeper

從上面咱們也能夠發現,好像哪都有ZooKeeper的身影,那什麼是ZooKeeper呢?咱們先去官網看看介紹:架構

官網對ZooKeeper的介紹

官網還有另外一段話:框架

ZooKeeper: A Distributed Coordination Service for Distributed Applications

相比於官網的介紹,我其實更喜歡Wiki中對ZooKeeper的介紹:分佈式

wiki介紹ZooKeeper

(留下不懂英語的淚水)學習

我簡單歸納一下:

  • ZooKeeper主要服務於分佈式系統,能夠用ZooKeeper來作:統一配置管理、統一命名服務、分佈式鎖、集羣管理。
  • 使用分佈式系統就沒法避免對節點管理的問題(須要實時感知節點的狀態、對節點進行統一管理等等),而因爲這些問題處理起來可能相對麻煩和提升了系統的複雜性,ZooKeeper做爲一個可以通用解決這些問題的中間件就應運而生了。

2、爲何ZooKeeper能幹這麼多?

從上面咱們能夠知道,能夠用ZooKeeper來作:統一配置管理、統一命名服務、分佈式鎖、集羣管理。

  • 這裏咱們無論統一配置管理、統一命名服務、分佈式鎖、集羣管理每一個具體的含義(後面會講)

那爲何ZooKeeper能夠幹那麼多事?來看看ZooKeeper到底是何方神物,在Wiki中其實也有提到:

ZooKeeper nodes store their data in a hierarchical name space, much like a file system or a tree) data structure

ZooKeeper的數據結構,跟Unix文件系統很是相似,能夠看作是一顆,每一個節點叫作ZNode。每個節點能夠經過路徑來標識,結構圖以下:

ZooKeeper結構圖

那ZooKeeper這顆"樹"有什麼特色呢??ZooKeeper的節點咱們稱之爲Znode,Znode分爲兩種類型:

  • 短暫/臨時(Ephemeral):當客戶端和服務端斷開鏈接後,所建立的Znode(節點)會自動刪除
  • 持久(Persistent):當客戶端和服務端斷開鏈接後,所建立的Znode(節點)不會刪除
ZooKeeper和Redis同樣,也是C/S結構(分紅客戶端和服務端)

Znode和Znode的類型

2.1 監聽器

在上面咱們已經簡單知道了ZooKeeper的數據結構了,ZooKeeper還配合了監聽器纔可以作那麼多事的。

常見的監聽場景有如下兩項:

  • 監聽Znode節點的數據變化
  • 監聽子節點的增減變化

監聽Znode節點的數據有無變化

監聽子節點的增減變化

沒錯,經過監聽+Znode節點(持久/短暫[臨時]),ZooKeeper就能夠玩出這麼多花樣了。

3、ZooKeeper是怎麼作到的?

下面咱們來看看用ZooKeeper怎麼來作:統一配置管理、統一命名服務、分佈式鎖、集羣管理。

3.1 統一配置管理

好比咱們如今有三個系統A、B、C,他們有三份配置,分別是ASystem.yml、BSystem.yml、CSystem.yml,而後,這三份配置又很是相似,不少的配置項幾乎都同樣。

  • 此時,若是咱們要改變其中一份配置項的信息,極可能其餘兩份都要改。而且,改變了配置項的信息極可能就要重啓系統

因而,咱們但願把ASystem.yml、BSystem.yml、CSystem.yml相同的配置項抽取出來成一份公用的配置common.yml,而且即使common.yml改了,也不須要系統A、B、C重啓。

系統A、B、C都使用着這份配置

作法:咱們能夠將common.yml這份配置放在ZooKeeper的Znode節點中,系統A、B、C監聽着這個Znode節點有無變動,若是變動了,及時響應。

系統A、B、C監聽着ZooKeeper的節點,一旦common.yml內容有變化,及時響應

參考資料:

3.2 統一命名服務

統一命名服務的理解其實跟域名同樣,是咱們爲這某一部分的資源給它取一個名字,別人經過這個名字就能夠拿到對應的資源。

好比說,如今我有一個域名www.java3y.com,但我這個域名下有多臺機器:

  • 192.168.1.1
  • 192.168.1.2
  • 192.168.1.3
  • 192.168.1.4

別人訪問www.java3y.com便可訪問到個人機器,而不是經過IP去訪問。

經過名稱去訪問旗下的IP

3.3 分佈式鎖

鎖的概念在這我就不說了,若是對鎖概念還不太瞭解的同窗,可參考下面的文章

咱們可使用ZooKeeper來實現分佈式鎖,那是怎麼作的呢??下面來看看:

系統A、B、C都去訪問/locks節點

系統A、B、C都去訪問locks節點

訪問的時候會建立帶順序號的臨時/短暫(EPHEMERAL_SEQUENTIAL)節點,好比,系統A建立了id_000000節點,系統B建立了id_000002節點,系統C建立了id_000001節點。

建立出臨時帶順序號的節點

接着,拿到/locks節點下的全部子節點(id_000000,id_000001,id_000002),判斷本身建立的是否是最小的那個節點

  • 若是是,則拿到鎖。

    • 釋放鎖:執行完操做後,把建立的節點給刪掉
  • 若是不是,則監聽比本身要小1的節點變化

舉個例子:

  • 系統A拿到/locks節點下的全部子節點,通過比較,發現本身(id_000000),是全部子節點最小的。因此獲得鎖
  • 系統B拿到/locks節點下的全部子節點,通過比較,發現本身(id_000002),不是全部子節點最小的。因此監聽比本身小1的節點id_000001的狀態
  • 系統C拿到/locks節點下的全部子節點,通過比較,發現本身(id_000001),不是全部子節點最小的。因此監聽比本身小1的節點id_000000的狀態
  • …...
  • 等到系統A執行完操做之後,將本身建立的節點刪除(id_000000)。經過監聽,系統C發現id_000000節點已經刪除了,發現本身已是最小的節點了,因而順利拿到鎖
  • ….系統B如上

3.4集羣狀態

通過上面幾個例子,我相信你們也很容易想到ZooKeeper是怎麼"感知"節點的動態新增或者刪除的了。

仍是以咱們三個系統A、B、C爲例,在ZooKeeper中建立臨時節點便可:

各維護一個臨時節點

只要系統A掛了,那/groupMember/A這個節點就會刪除,經過監聽groupMember下的子節點,系統B和C就可以感知到系統A已經掛了。(新增也是同理)

除了可以感知節點的上下線變化,ZooKeeper還能夠實現動態選舉Master的功能。(若是集羣是主從架構模式下)

原理也很簡單,若是想要實現動態選舉Master的功能,Znode節點的類型是帶順序號的臨時節點(EPHEMERAL_SEQUENTIAL)就行了。

  • Zookeeper會每次選舉最小編號的做爲Master,若是Master掛了,天然對應的Znode節點就會刪除。而後讓新的最小編號做爲Master,這樣就能夠實現動態選舉的功能了。

最後

這篇文章主要講解了ZooKeeper的入門相關的知識,ZooKeeper經過Znode的節點類型+監聽機制就實現那麼多好用的功能了!

固然了,ZooKeeper要考慮的事沒那麼簡單的,後面有機會深刻的話,我還會繼續分享,但願這篇文章對你們有所幫助~

參考資料:

樂於輸出 乾貨的Java技術公衆號:Java3y。公衆號內有200多篇 原創技術文章、海量視頻資源、精美腦圖,不妨來 關注一下!

帥的人都關注了

以爲個人文章寫得不錯,不妨點一下

相關文章
相關標籤/搜索