5.Watcher机制(二)WatchManager

简介: 本文深入分析ZooKeeper服务端的WatchManager类,详解其核心属性与方法。该类通过watchTable和watch2Paths两个映射管理Watcher与节点路径的双向关系,支持添加、移除及触发Watcher,并确保多线程安全,是ZooKeeper事件通知机制的关键实现。

一、前言
  前面已经分析了Watcher机制中的第一部分,即在org.apache.zookeeper下的相关类,接着来分析org.apache.zookeeper.server下的WatchManager类。
二、WatchManager源码分析
2.1 类的属性 
说明:WatcherManager类用于管理watchers和相应的触发器。watchTable表示从节点路径到watcher集合的映射,而watch2Paths则表示从watcher到所有节点路径集合的映射。
2.2 核心方法分析

  1. size方法
    说明:可以看到size方法是同步的,因此在多线程环境下是安全的,其主要作用是获取watchTable的大小,即遍历watchTable的值集合。
  2. addWatch方法
    说明:addWatch方法同样是同步的,其大致流程如下
      ① 通过传入的path(节点路径)从watchTable获取相应的watcher集合,进入②
      ② 判断①中的watcher是否为空,若为空,则进入③,否则,进入④
      ③ 新生成watcher集合,并将路径path和此集合添加至watchTable中,进入④【类似缓存操作】
      ④ 将传入的watcher添加至watcher集合,即完成了path和watcher添加至watchTable的步骤,进入⑤
      ⑤ 通过传入的watcher从watch2Paths中获取相应的path集合,进入⑥
      ⑥ 判断path集合是否为空,若为空,则进入⑦,否则,进入⑧
      ⑦ 新生成path集合,并将watcher和paths添加至watch2Paths中,进入⑧
      ⑧ 将传入的path(节点路径)添加至path集合,即完成了path和watcher添加至watch2Paths的步骤。
    综上:addWatche方法会将:
    1.入参所对应的watcher添加到入参path所对应的全部Watcher集合中,如path下已有则添加,没有创建新的并添加进去;
    2.入参所对应的path添加到入参watcher所对应给的所有路径集合中,如watcher对应路径为空则创建新的集合进行添加,非空将入参path直接添加进去。
  3. removeWatcher方法  
    说明:removeWatcher用作从watch2Paths和watchTable中中移除该watcher,其大致步骤如下
      ① 从watch2Paths中移除传入的watcher,并且返回该watcher对应的路径集合,进入②
      ② 判断返回的路径集合是否为空,若为空,直接返回,否则,进入③
      ③ 遍历②中的路径集合,对每个路径,都从watchTable中取出与该路径对应的watcher集合,进入④
      ④ 若③中的watcher集合不为空,则从该集合中移除watcher,并判断移除元素后的集合大小是否为0,若为0,进入⑤
      ⑤ 从watchTable中移除路径
  4. triggerWatch方法
    Java
    运行代码
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public Set triggerWatch(String path, EventType type, Set supress) {
    // 根据事件类型、连接状态、节点路径创建WatchedEvent
    WatchedEvent e = new WatchedEvent(type, KeeperState.SyncConnected, path);

    // watcher集合
    HashSet watchers;
    synchronized (this) { // 同步块

     // 从watcher表中移除path,并返回其对应的watcher集合
     watchers = watchTable.remove(path);
     if (watchers == null || watchers.isEmpty()) { // watcher集合为空
         if (LOG.isTraceEnabled()) { 
             ZooTrace.logTraceMessage(LOG, ZooTrace.EVENT_DELIVERY_TRACE_MASK,
                                      "No watchers for " + path);
         }
         // 返回
         return null;
     }
     for (Watcher w : watchers) { // 遍历watcher集合
         // 根据watcher从watcher表中取出路径集合
         HashSet<String> paths = watch2Paths.get(w);
         if (paths != null) { // 路径集合不为空
             // 则移除路径
             paths.remove(path);
         }
     }
    

    }
    for (Watcher w : watchers) { // 遍历watcher集合

     if (supress != null && supress.contains(w)) { // supress不为空并且包含watcher,则跳过
         continue;
     }
     // 进行处理
     w.process(e);
    

    }
    return watchers;
    }
     说明:该方法主要用于触发watch事件,并对事件进行处理。其大致步骤如下
      ① 根据事件类型、连接状态、节点路径创建WatchedEvent,进入②
      ② 从watchTable中移除传入的path对应的键值对,并且返回path对应的watcher集合,进入③
      ③ 判断watcher集合是否为空,若为空,则之后会返回null,否则,进入④
      ④ 遍历②中的watcher集合,对每个watcher,从watch2Paths中取出path集合,进入⑤
      ⑤ 判断④中的path集合是否为空,若不为空,则从集合中移除传入的path。进入⑥
      ⑥ 再次遍历watcher集合,对每个watcher,若supress不为空并且包含了该watcher,则跳过,否则,进入⑦
      ⑦ 调用watcher的process方法进行相应处理,之后返回watcher集合。【这里的process具体怎么执行的呢】

  5. dumpWatches方法
    Java
    运行代码
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public synchronized void dumpWatches(PrintWriter pwriter, boolean byPath) {
    if (byPath) { // 控制写入watchTable或watch2Paths
     for (Entry<String, HashSet<Watcher>> e : watchTable.entrySet()) { // 遍历每个键值对
         // 写入键
         pwriter.println(e.getKey());
         for (Watcher w : e.getValue()) { // 遍历值(HashSet<Watcher>)
             pwriter.print("\t0x");
             pwriter.print(Long.toHexString(((ServerCnxn)w).getSessionId()));
             pwriter.print("\n");
         }
     }
    
    } else {
     for (Entry<Watcher, HashSet<String>> e : watch2Paths.entrySet()) { // 遍历每个键值对
         // 写入"0x"
         pwriter.print("0x");
         pwriter.println(Long.toHexString(((ServerCnxn)e.getKey()).getSessionId()));
         for (String path : e.getValue()) { // 遍历值(HashSet<String>)
             // 
             pwriter.print("\t");
             pwriter.println(path);
         }
     }
    
    }
    }
      说明:dumpWatches用作将watchTable或watch2Paths写入磁盘。
    三、总结
      WatchManager类用作管理watcher、其对应的路径以及触发器,其方法都是针对两个映射的操作。
相关文章
|
算法 应用服务中间件 nginx
超越内存限制:深入探索内存池的工作原理与实现
这篇文章将深入探索内存池的工作原理与实现,介绍如何超越传统的内存限制。首先,我们将了解什么是内存池以及它与传统内存分配方式的不同之处。接着,我们将探索内存池的工作原理,包括内存池的数据结构和算法。我们还将解释内存池如何提升性能,避免内存碎片化,并减少内存分配的开销。此外,我们将介绍一些常见的内存池实现技术,例如固定大小内存池和动态大小内存池,并对比它们的优劣之处。
525 0
|
10月前
|
存储 运维 Oracle
服务器数据恢复—存储硬盘指示灯亮黄灯,RAID5阵列崩溃的数据恢复案例
服务器存储数据恢复环境: 某单位一台某品牌DS5300存储,1个机头+4个扩展柜,50块的硬盘组建了两组RAID5阵列。一组raid5阵列有27块硬盘,存放Oracle数据库文件。存储系统上层一共划分了11个卷。 服务器存储故障: 存储设备上两个硬盘指示灯亮黄色。其中一组RAID5阵列崩溃,存储不可用,设备已经过保。
|
7月前
|
人工智能 JSON Cloud Native
破解 AI Agent 搭建师职业焦虑:从调参到工程化的能力跃迁
随着大模型原生推理能力提升与低代码平台普及,AI Agent搭建师正面临“上下夹击”:上层被模型自动规划替代,下层被可视化编排覆盖。破局关键在于转向“确定性工程”——聚焦业务SOP工程化、全流程自动化评估、鲁棒性架构设计,成长为懂业务的AI架构师或精工程的AI系统工程师。(239字)
432 4
|
7月前
|
存储 缓存 安全
2026年阿里云服务器最新活动价格,热门实例规格配置、带宽、云盘收费标准与活动价格
2026年阿里云服务器价格优惠,提供轻量云服务器2核2G一年38元、e实例云服务器2核2G一年99元等多款特价实例,覆盖经济型e、通用算力型u1、u2a、计算型c9i等热门规格,满足不同场景需求。其中,经济型e实例以高性价比、企业级服务质量和安全保障脱颖而出;u1实例提供高性能与灵活配置,适合通用上云;u2a实例则基于AMD CPU平台,专为对成本敏感且追求均衡性能的用户设计。
712 0
2026年阿里云服务器最新活动价格,热门实例规格配置、带宽、云盘收费标准与活动价格
|
8月前
|
存储 弹性计算 Linux
阿里云服务器购买配置选择攻略:地域、实例、带宽与操作系统选择注意事项
云服务器已成为个人博客、企业官网、APP后端支持以及小程序运行等场景不可或缺的基础设施。然而,对于初次接触云服务的新手用户来说,如何选择适合自己的阿里云服务器配置,尤其是地域、实例、带宽与操作系统等方面,可能会感到困惑。本文将为大家解析阿里云服务器购买的各个环节的注意事项,为新手用户提供详尽的选购指南。
311 3
|
8月前
|
缓存 监控 JavaScript
前端性能监控指标
前端性能指标包括白屏时间、首屏时间、DOM可操作时间和页面总加载时间。可通过注入代码或`window.performance` API进行量化统计,后者基于浏览器标准接口,提供精确的网络、解析与渲染各阶段耗时数据,助力性能优化。
|
C++ 开发者
C++课程设计:图书管理系统【附源码】
图书管理系统,C++ 实现,附全套源码
5921 2
C++课程设计:图书管理系统【附源码】
|
Java API 数据库
使用Spring Boot构建RESTful API
使用Spring Boot构建RESTful API
|
安全 中间件 应用服务中间件
ctfshow-web4(文件包含&日志注入)
ctfshow-web4(文件包含&日志注入)
1005 0

热门文章

最新文章