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)