ZooKeeper學習筆記(二)——內部原理

zookeeper學習筆記(二)——內部原理

1. zookeeper的節點的類型

總的來說可以分爲持久型和短暫型,主要區別如下:

  • 持久:客戶端與服務器端斷開連接的以後,創建的節點不會被刪除;
    • 持久化目錄節點:客戶端與zookeeper斷開連接之後,該節點依舊會存在;
    • 持久化順序編號目錄節點:客戶端與zookeeper斷開連接之後,該節點依舊會存在,只是zookeeper會給該節點名稱進行順序編號;
  • 短暫:客戶端和服務端斷開連接之後,創建的節點自己刪除
    • 臨時目錄節點:客戶端與zookeeper斷開連接之後,該節點會被刪除;
    • 臨時順序編號節點:客戶端與zookeeper斷開連接之後,該節點被刪除,只是zookeeper給該節點名稱進行順序編號。

要說明的是創建znode的時候設置的順序標識,znode名稱後邊會附加一個值,順序號只是一個單調遞增的計數器,由父節點維護。

在分佈式系統中,順序號可以被用於所有的事件進行全局的排序,這樣客戶端可以通過順序號推斷事件的順序。

2. Stat結構體

1)czxid-創建節點的事務zxid,每次修改ZooKeeper狀態都會收到一個zxid形式的時間戳,也就是ZooKeeper事務ID。事務ID是ZooKeeper中所有修改總的次序。每個修改都有唯一的zxid,如果zxid1小於zxid2,那麼zxid1在zxid2之前發生。
2)ctime - znode被創建的毫秒數(從1970年開始)
3)mzxid - znode最後更新的事務zxid
4)mtime - znode最後修改的毫秒數(從1970年開始)
5)pZxid-znode最後更新的子節點zxid
6)cversion - znode子節點變化號,znode子節點修改次數
7)dataversion - znode數據變化號
8)aclVersion - znode訪問控制列表的變化號
9)ephemeralOwner- 如果是臨時節點,這個是znode擁有者的session id。如果非臨時節點則是0。
10)dataLength- znode的數據長度
11)numChildren - znode子節點數量

3. 監聽器原理(重點內容)

我們在之前已經瞭解過,註冊進zookeeper的客戶端會監聽它所關心的節點,當節點發生變化的時候,zookeeper會通知給客戶端。zookeeper主要是爲了統一分佈式系統中各個節點的工作狀態,在資源衝突的情況下協調提供節點資源搶佔,提供給每個節點了解整個集羣所處狀態的途徑。這一切的實現都依賴於zookeeper中的事件監聽和通知機制

大致原理:zookeeper維護着一個watchList,裏面是對某個節點的觀察者對象,一旦發生變化,就會遍歷這個watchList,挨個通知它們。

通過追蹤代碼,來看一下zookeeper的異步通信原理:

  • 首先代碼在執行的時候創建了一個Zookeeper對象

  • 代碼進入到了Zookeeper()方法,可以看到它是在調用自己的另外一個構造方法:

  • 繼續跟進:這個方法裏面生成了兩個線程,zookeeper的客戶端和服務端通信時異步的,異步一定有子線程

  • 這是兩個Thread的子類

  • 在原來創建創建ClientCnxn的方法下邊,有一個start方法:

  • 繼續跟進去:

ok~到這可以清楚的看到,我們在創建Zookeeper對象的時候就生成了兩個子線程,sendTreadeventThread

總結:所有的註冊請求都是通過sendThread發給服務端的,而eventThread就是等待着服務端的通知,一旦接收到了通知,就去回調Process()方法。

一個形象的小栗子:

A老闆有兩個小祕書,一個叫sendThread,另一個叫做eventThread。有一天A老闆要給B老闆發消息,那麼sendThread小祕書就會去執行老闆的發消息任務,而eventThread就等着B老闆的回信,它一旦接收到回信,就去通知A老闆~ 。

4. ZooKeeper的ZAB理論(重點)

zookeeper是如何保證在分佈式高併發情況下數據讀寫有序並且全局一致的?

通過ZAB協議保證的:Zookeeper Atomic Broadcast ,即Zookeeper 原子廣播。

主要內容就是兩個部分:① 沒有leader選leader【崩潰恢復】,② 有leader就開始幹活【正常讀寫】

那麼接下來就討論,怎麼選leader 有了leader之後怎麼幹活~

4.1 選舉機制

4.1.1 zookeeper集羣中節點的狀態:

  • Looking :集羣剛啓動時,所有的節點都是Looking狀態,即尋找leader狀態。該狀態無法對外提供服務,其他狀態都可以。
  • Abserving: 爲了快速擴展集羣,在小範圍內leader帶着follower投票執行寫,投票成功後通知給observers去寫,保證了擴展集羣時寫的性能。【適用場景:集羣大 、跨數據中心】
  • Following: follower
  • Leading:leader

1)半數機制:集羣中半數以上機器存活,集羣可用。所以Zookeeper適合安裝奇數臺服務器。

2)Zookeeper雖然在配置文件中並沒有指定Master和Slave。但是,Zookeeper工作時,是有一個節點爲Leader,其他則爲Follower,Leader是通過內部的選舉機制臨時產生的。

3)以一個簡單的例子來說明整個選舉的過程。

假設有五臺服務器組成的Zookeeper集羣,它們的id從1-5,同時它們都是最新啓動的,也就是沒有歷史數據,在存放數據量這一點上,都是一樣的。假設這些服務器依序啓動,來看看會發生什麼,如圖所示。

(1)服務器1啓動,發起一次選舉。服務器1厚顏無恥投自己一票。此時服務器1票數一票,不夠半數以上(3票),選舉無法完成,服務器1狀態保持爲LOOKING;

(2)服務器2啓動,再發起一次選舉。服務器1和2分別投自己一票並交換選票信息:此時服務器1發現服務器2的ID比自己目前投票推舉的(服務器1)大,更改選票爲推舉服務器2。此時服務器1票數0票,服務器2票數2票,沒有半數以上結果,選舉無法完成,服務器1,2狀態保持LOOKING

(3)服務器3啓動,發起一次選舉。此時服務器1和2都會更改選票爲服務器3。此次投票結果:服務器1爲0票,服務器2爲0票,服務器3爲3票。此時服務器3的票數已經超過半數,服務器3當選Leader。服務器1,2更改狀態爲FOLLOWING,服務器3更改狀態爲LEADING;

(4)服務器4啓動,發起一次選舉。此時服務器1,2,3已經不是LOOKING狀態,不會更改選票信息。交換選票信息結果:服務器3爲3票,服務器4爲1票。此時服務器4服從多數,更改選票信息爲服務器3,並更改狀態爲FOLLOWING;

(5)服務器5啓動,同4一樣當小弟。

注意:選leader時先比較zxid(數據版本),再比較myid

4.2 寫數據流程

1)Client 向 ZooKeeper 的 Server1 上寫數據,發送一個寫請求。
2)如果Server1不是Leader,那麼Server1 會把接受到的請求進一步轉發給Leader,因爲每個ZooKeeper的Server裏面有一個是Leader。這個Leader 會將寫請求廣播給各個Server,比如Server1和Server2,各個Server會將該寫請求加入待寫隊列,並向Leader發送成功信息。
3)當Leader收到半數以上 Server 的成功信息,說明該寫操作可以執行。Leader會向各個Server 發送提交信息,各個Server收到信息後會落實隊列裏的寫請求,此時寫成功。
4)Server1會進一步通知 Client 數據寫成功了,這時就認爲整個寫操作成功。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章