在大數據領域,Zookeeper 是一種高可用的分布式協調服務框架,廣泛應用于各種分布式系統場景。其中,Watcher API 是 Zookeeper 提供的一項強大功能,它允許我們實時監控節點數據的變化并接收相應的通知。將介紹如何利用 Watcher API 來監控節點數據的變動。
Watcher API 實現了一種事件機制,當節點數據發生變化時,Zookeeper 會主動向客戶端發送事件通知。客戶端可以通過注冊 Watcher 來接收這些通知。Watcher API 的核心思想基于觀察者模式,當節點數據變化時,Zookeeper 會將事件信息發送給監聽該節點的客戶端,從而實現實時的數據監控與通知。
使用Watcher可以解決應用服務器集群中可能存在的兩個問題:
1、當某個通用的配置發生變化后,可以實現自動的讓所有服務器的配置統一生效。
2、當集群中某個節點宕機,可以通知集群中的其他節點知道,進行處理。
為了解決這兩個問題,Zookeeper引入了Watcher機制來實現監聽和同步的功能,能夠讓多個節點同時監聽某一個對象,當這個對象自身狀態發生變化時,會通知所有監聽者。Zookeeper中實現Watcher需要有三個部分,分別是Zookeeper服務端、客戶端以及客戶端的WatchManager。客戶端向Zookeeper注冊Watcher的同時,會將客戶端的Watcher對象存儲在客戶端的WatchManager中;Zookeeper服務器觸發Watcher事件后,會向客戶端發送通知,客戶端線程從WatchManager中取出對應Watcher執行。
Watch機制
當Zookeeper中節點 Znode 發生變化時(包括 Znode 的增加、刪除、修改,以及子 Znode 的變動),客戶端可以通過 Watch 機制接收到通知。要實現 Watch,必須實現 org.apache.zookeeper.Watcher 接口,并將實現類的實例傳遞給相應的 Watch 方法。在 Zookeeper 中,所有的讀操作(如 getData()、getChildren() 和 exists())都可以設置 Watch 選項。值得注意的是,Watch 事件具有一次性觸發的特性,也就是說,如果被監視的 Znode 發生變化,Zookeeper 會通知設置了該 Watch 的客戶端。如果我們需要Watcher,可以自定義Watcher,如果是Boolean型變量,當為true時,則使用系統默認的Watcher,系統默認的Watcher是在Zookeeper的構造函數中定義的Watcher。參數中Watcher為空或者false,表示不啟用Wather。
Watch的一次性觸發
當客戶端在某個 Znode 上設置了 Watch 后,如果該 Znode 的內容發生變化,客戶端將收到相應的 Watch 事件。但如果 /znode1 隨后再次發生變化,客戶端將無法再接收到新的 Watch 事件,除非重新設置 Watch。
Watch的異步發送至客戶端
Watch 事件是異步發送給客戶端的,Zookeeper 保證客戶端發送的更新順序是有序的。若某個 Znode 沒有設置 Watcher,客戶端在 Watch 被發送到集群之前,對該 Znode 的任何變化都不會被感知,若服務器端沒有相應的 Watcher,Znode 的變更不會通知客戶端。此外,即使某個 Znode 設置了 Watcher,并在發生變化時通知了客戶端,如果客戶端在接收到該變化事件后沒有立即重新設置 Watch,而其他客戶端又對該 Znode 進行了修改,那么客戶端將無法接收到該 Znode 的第二次變化通知。因此,在使用 Zookeeper 時,不能期望監控到每一次節點的變化,Zookeeper 只能保證最終一致性,而非強一致性。
設置 Watch 的數據內容
Znode 的變化方式多種多樣,Zookeeper 維護了兩個 Watch 列表:一個用于節點數據的 Watch,另一個用于子節點的 Watch。調用 getData() 和 exists() 方法會設置數據 Watch,而 getChildren() 則設置子節點 Watch。用戶可以根據不同的返回結果選擇合適的 Watch 類型。
總結
我們可以通過業務實際情況來使用Zookeeper的Watcher來實現節點數據的同步,Watch 是一種輕量級的機制,實際上只是本地 JVM 的回調。服務器端僅僅記錄了是否設置了 Watcher 的布爾值。在服務器端處理相應的 Znode 操作,并根據客戶端傳遞的 Watcher 信息進行持久化。同時作為 Watcher 的回調,監聽服務器端事件的變化。當批準某次 Znode 變更請求后,會向 Zookeeper 客戶端發送通知信息,Zookeeper 客戶端在接收到通知信息后,會查找對應路徑的 Watcher 列表,并逐個觸發相應的回調,以此實現節點數據的同步。