Watch是ZooKeeper中非常重要的一個機制,它可以監控ZooKeeper中節點的變化情況,告知用戶端。下面,我們以代碼為例來分析Watch在ZooKeeper中是如何實作的。ZooKeeper中一共由三種方法可以實作Watch,分别為getData、exists和getChildren,今天我們先來看下getChildren()方法:
3、getChildren
執行結果如下:
而當我們在擷取子目錄節點清單getChildren()方法調用之後,接着調用修改根目錄節點資料的setData()方法,添加代碼和結果如下:
它仍然隻是監控根目錄下的子節點變化情況,而且觸發的是NodeChildrenChanged事件!而當我們在建立第一個子節點後如果再建立它的一個子節點,并且在建立之前還是先擷取根目錄/tmp_root_path節點的子目錄節點列,執行結果會怎麼樣呢?添加的代碼和執行結果如下:
還是隻會監控直接子目錄下的節點,在增加第二個節點時觸發NodeChildrenChanged事件,并不會越級監控!當然,出現org.apache.zookeeper.KeeperException$NotEmptyException異常是因為我們删除第一個節點時,由于其還有節點,是以才會報錯!
還有一件有意思的事情,當我們在修改第一個子節點資料前擷取根目錄/tmp_root_path節點的子目錄節點清單,調用getChildren()方法,結果會怎樣呢?添加處的代碼和執行結果如下:
也是隻監控一次,但是,但是,但是,它隻監控根目錄子節點的增減情況,至于資料是否發生變化,完全不會監控!這也正是為什麼修改第一個子節點資料沒有觸發,而删除第一個子節點時會觸發NodeChildrenChanged事件的原因!
結論:
getChildren()方法僅僅監控對應節點直接子目錄的一次變化,但是隻會監控直接子節點的增減情況,不會監控資料變化情況!若要每次對應節點發生增減變化都被監測到,那麼每次都得先調用getChildren()方法擷取一遍節點的子節點清單!