【Zookeeper】01_系統模型


Zookeeper模型分成數據模型,節點特性,版本,Watcher,ACL五個部分。

1 數據模型

  • 樹形結構:每個節點成爲ZNode,是數據的最小單元,每個節點可以存放數據或者是子節點。
  • 事務ID:ZXID,每次對服務器狀態進行操作(節點創建與刪除;節點內容更新;客戶端會話與失效),就會分配全局的事務ID

2 節點類型

根據節點生命週期長短分成持久節點,臨時節點,順序節點

  • 持久節點:一直存在服務端,直到手動刪除。
  • 臨時節點:生命週期是客戶端的會話失效週期,不是TCP斷開連接。臨時節點只能作爲葉子節點,不能基於臨時節點創建子節點。
  • 順序節點:節點可能還表現爲順序特性,即節點在父節點列表中是否標記創建順序。

3 狀態信息

節點信息包含節點數據內容以及狀態信息。

  • czxid:reated ZXID,表示該節點被創建時的事務ID
  • mzxid:Modified ZXID,表示該節點最後一次被更新時的事務ID
  • ctime:表示節點被創建的時間
  • mtime:表示該節點最後一次被更新時的時間
  • version:數據節點的版本號。節點被創建後,被更新過的次數,即使更新的內容與原內容相同,也視爲一次更新
  • cversion:子節點的版本號
  • aversion:節點的ACL版本號
  • ephemeralOwner:創建該臨時節點的會話的SessionID。如果該節點爲持久節點,那麼這個屬性值爲0
  • dataLength:數據內容的長度
  • numChildren:當前節點的子節點個數
  • pzxid:表示該節點的子節點列表最後一次被修改時的事務ID。只有子節點列表變更了纔會變更pzxid,子節點內容變更不會影響pzxid

4 Watcher機制

一對多的發佈訂閱模式,客戶端向服務端註冊watcher,監聽某一特定主題的對象,當主題對象自身發生變化時,會通知所有的訂閱者。

4.1 Watcher基礎

Watcher機制的對象包括:

  • 客戶端線程
  • 客戶端WatcherManager
  • 服務端

Watcher機制:

  1. 客戶端向服務端註冊watcher同時會把watcher對象存入客戶端WatcherManager中
  2. 當服務端觸發Watcher事件後,服務端會向客戶端發送通知
  3. 客戶端線程從WatcherManager中取出對應的Watcher對象,執行回調邏輯。

Watcher特性包含:

  • 註冊一次性。watcher一旦被觸發,就會被刪除。如果需要監聽,就要手動註冊。否則一些更新比較頻繁的節點,每次變動都要不斷地將通知反饋給客戶端,對與網絡以及服務端性能影響很大。
  • 客戶端Watcher回調是串行同步的,保證了每個wathcer的順序。
  • 輕量級watcher。WatchedEvent是Watcher機制的最小通知單元,只包含了通知狀態,事件類型,節點路徑,不給出具體的變化內容,需要客戶端自己去相應節點獲取變化的內容,保證了客戶端服務端交互的數據量級。

4.2 Watcher事件

Watcher通知狀態與事件類型
在這裏插入圖片描述
注意:

  • NodeDataChanged:與dataVersion一致,即使變更內容前後一樣,也會觸發此事件。
  • NodeChildrenChanged:所關注的節點的子節點列表有變化。這裏說的變化是指子節點的個數和組成,具體到子節點內容的變化是不會通知的。

4.3 process回調方法

WatchedEvent包含三個屬性:事件狀態keeperstate,事件類型EventType,節點路徑path。

abstract public void process(WatchedEvent event);

在這裏插入圖片描述
在這裏插入圖片描述

WatcherEvent與WatchedEvent:

  • WatchedEvent表示服務端與客戶端之間的邏輯對象
  • WatcherEvent實現了序列化接口,可用於網絡傳輸
  • 服務端生成WatchedEvent後調用getWrapper方法包裝成可序列化的WatcherEvent事件,以便傳輸到客戶端;客戶端接到後將WatcherEvent轉換成WatchedEvent,使用process進行處理

4.4 Watcher工作機制

watcher註冊機制包括:

  • 客戶端註冊Watcher
  • 服務端處理Watcher
  • 客戶端回調Watcher

4.4.1 客戶端註冊Watcher

在這裏插入圖片描述
在這裏插入圖片描述

/**
 */
public interface ClientWatchManager {
    /**
     * Return a set of watchers that should be notified of the event. The 
     * manager must not notify the watcher(s), however it will update it's 
     * internal structure as if the watches had triggered. The intent being 
     * that the callee is now responsible for notifying the watchers of the 
     * event, possibly at some later time.
     * 
     * @param state event state
     * @param type event type
     * @param path event path
     * @return may be empty set but must not be null
     */
    public Set<Watcher> materialize(Watcher.Event.KeeperState state,
        Watcher.Event.EventType type, String path);
}

關鍵類

  • ZooKeeper:客戶端基礎類、存儲了ClientCnxn和ZkWatcherManager
  • ZKWatchManager:ZooKeeper的內部類,實現了ClientWatchManager接口,主要用來存儲各種類型的Watcher,主要有三種:dataWatches、existWatches、childWatches以及一個默認的defaultWatcher。
  • ClientCnxn:與服務端的交互類,主要包含以下對象:outgoingQueue、SendThread和EventThread。
    1. 其中outgoingQueue未待發送給服務端的Packet列表,
    2. SendThread線程負責和服務端進行請求交互
    3. EventThread線程則負責客戶端Watcher事件的回調執行
  • WatchRegistration:Zookeeper的內容類,包裝了Watcher和clientPath,並且負責Watcher的註冊
  • Packet:ClientCnxn的內部類,與Zookeeper服務端通信的交互類

客戶端處理步驟:

  1. 創建zk客戶端對象實例時註冊watcher,這個 Watcher 將作爲整個 ZooKeeper 會話期間的默認 Watcher,它會一直被保存在客戶端 ZKWatchManagerdefaultWatcher 裏面。(getData, getChildren, exists方法中也可以註冊watcher)
  2. 例如getData註冊Watcher後,客戶端會向當前的request標記,設置爲“使用watcher監聽”,同時封裝WatcherRegistration對象用於暫時保存數據節點路徑和wathcer對應關係。
  3. WatchRegistration被封裝成Packet對象,放入發送隊列等待客戶端發送。客戶端沒有把Watcher對象發送給服務端,只是將request與requestHeader兩個屬性序列化傳輸,否則服務端就容易出現內存緊張甚至溢出的危險。
  4. ZKWatcherManager.dataWatches是Map<String, Set>保存數據節點路徑與Watcher對象關係。

4.4.2 服務端處理Watcher

對於註冊 Watcher 請求,FinalRequestProcessor 的 ProcessRequest 方法會判斷當前請求是否需要註冊 Watcher,如果爲 true,就會將當前的 ServerCnxn 對象和數據節點路徑傳入 getData 方法中去。ServerCnxn 是一個 ZooKeeper 客戶端和服務器之間的連接接口,代表了一個客戶端和服務器的連接,我們後面講到的 process 回調方法,實際上也是從這裏回調的,所以可以把 ServerCnxn 看作是一個 Watcher 對象。數據節點的節點路徑和 ServerCnxn 最終會被存儲在 WatchManager 的 watchTable 和 watch2Paths 中。
WatchManager 負責 Watcher 事件的觸發,它是一個統稱,在服務端 DataTree 會託管兩個 WatchManager,分別是watchTable和 watch2Paths,分別對應數據變更 Watcher 和節點變更 Watcher。

當DataTree中節點數據內容或版本發生變化或節點變更時,會調用相應方法去觸發 WatchManager 的 triggerWatch 方法,該方法返回 ZNODE 的信息,自此進入到回調本地 process 的序列。

4.4.3 客戶端回調Watcher

SendThread的response()方法負責接收這個客戶端事件通知。首先會對replyHeader中xid進行判斷,如果是-1,則說明是一個通知類型的響應。作以下處理:

  1. 反序列化:ZooKeeper客戶端接到請求後,首先將字節流轉換成WatcherEvent對象。
  2. 處理chrootPath:如果客戶端設置了chrootPath屬性,那麼需要對服務端傳過來的完整的節點路徑進行chrootPath處理,生成客戶端的一個相對節點路徑。
  3. 還原WatchedEvent:將WatcherEvent對象轉換成WatchedEvent。
  4. 回調Watcher:將WatchedEvent對象交給EventThread線程,在下一個輪詢週期中進行Watcher回調。

5 ACL保障數據安全

用於對節點的權限進行控制,一個有效的ACL信息包含:權限模式(Scheme),授權對象(ID),權限(Permission),即"scheme:ID:permission"。

參考

  • https://www.cnblogs.com/shamo89/p/9787176.html
  • 圖比較詳細,https://www.cnblogs.com/ZhuChangwu/p/11593642.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章