zk作為一款成熟的分布式協調框架,訂閱-發布功能是很重要的一個。所謂訂閱發布功能,其實說白了就是觀察者模式。觀察者會訂閱一些感興趣的主題,然后這些主題一旦變化了,就會自動通知到這些觀察者。
zk的訂閱發布也就是watch機制,是一個輕量級的設計。因為它采用了一種推拉結合的模式。一旦服務端感知主題變了,那么只會發送一個事件類型和節點信息給關注的客戶端,而不會包括具體的變更內容,所以事件本身是輕量級的,這就是所謂的“推”部分。然后,收到變更通知的客戶端需要自己去拉變更的數據,這就是“拉”部分。
watch機制
一、目標是誰?
zode /path (節點操作來觸發watch)
1、創建
2、修改
3、刪除
4、查詢
5、是否存在
二、使用
可以注冊watcher的方法:getData、exists、getChildren。
public static void main(String[] args) throws KeeperException { try { // 連接 ZooKeeper connect = zookeeperConnection.connect("192.168.44.5:2181"); // 注冊watch connect.getData("/alex",new GetMyWatch(),connect.exists("/alex",false)); // 因為是main方法,使用此方法保證線程不被停止 System.in.read(); } catch (Exception e) { e.printStackTrace(); } } /** * 自定義監聽器 */ private static class GetMyWatch implements Watcher{ @Override public void process(WatchedEvent watchedEvent) { System.out.println(watchedEvent.getState()); System.out.println("getData 數據回調"); } }
可以觸發watcher的方法:create、delete、setData。連接斷開的情況下觸發的watcher會丟失。
修改此節點,觀察watch是否被調用

可以觀察到watch 被調用了,但是在這里有一個注意的地方,watch是一次性的,只會被調用一次,你在后面再次修改節點,watch是不會被調用的

1、一次性的觸發器(one-time trigger)
發送給客戶端(Sent to the client)
這個表明了Watch的通知事件是從服務器發送給客戶端的,是異步的,這就表明不同的客戶端收到的Watch的時間可能不同,但是ZooKeeper有保證:當一個客戶端在看到Watch事件之前是不會看到結點數據的變化的。例如:A=3,此時在上面設置了一次Watch,如果A突然變成4了,那么客戶端會先收到Watch事件的通知,然后才會看到A=4。 Zookeeper 客戶端和服務端是通過 Socket 進行通信的,由於網絡存在故障,所以監視事件很有可能不會成功地到達客戶端,監視事件是異步發送至監視者的,Zookeeper 本身提供了保序性(ordering guarantee):即客戶端只有首先看到了監視事件后,才會感知到它所設置監視的 znode 發生了變化(a client will never see a change for which it has set a watch until it first sees the watch event). 網絡延遲或者其他因素可能導致不同的客戶端在不同的時刻感知某一監視事件,但是不同的客戶端所看到的一切具有一致的順序。
3、被設置Watch的數據(The data for which the watch was set)
