热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ZooKeeper源码解析(10)Watcher实现

我们知道,ZooKeeper有一个非常重要的功能,就是做分布式锁.而这个分布式锁,就是通过ZooKeeper的Watcher来实现的.在这篇文章中,我们将会介绍,在ZooKeepe

我们知道,ZooKeeper有一个非常重要的功能,就是做分布式锁.而这个分布式锁,就是通过ZooKeeper的Watcher来实现的.

在这篇文章中,我们将会介绍,在ZooKeeper中,Watcher到底是如何实现的.

ZooKeeper Watch介绍

在ZooKeeper中,有三个读操作:getData(), getChildren(), exists(),都接受一个叫做Watch参数.

在ZooKeeper中,有两种Watch,分别是data watcheschild watchesgetData()和exists()会设置data watches,而getChildren()会设置child watches

Watch是由服务器端维护的一个集合,它会为每个客户端维护这么一个集合.

setData()会触发对应的znode上的data watchescreate()会触发对应znode的data watches以及它的父节点的child watchesdelete()会触发对应znode的data watches以及child watches,以及其父节点的child watches

Watches只会被触发一次.

更多关于Watch的介绍,请到这里

ZooKeeper中Watch的实现

ZooKeeper中,有一个Watcher接口:

《ZooKeeper源码解析(10)-Watcher实现》

这个Watcher接口中,定义了一个方法:process(WatchedEvent event)

就是这个方法,定义了当事件被触发时,要进行的操作.

而实现Watcher接口的类,有三个,都是我们很熟悉的:

  • ServerCnxn
  • NIOServerCnxn
  • NettyServerCnxn

我们这里主要看一下NIOServerCnxn中的实现:

《ZooKeeper源码解析(10)-Watcher实现》

我们可以看到,其process(WatchEvent event)方法,就是将WatchEvent发送给客户端.

ZooKeeper中Watch的原理

在之前的文章中,我们介绍请求处理的时候,提到了有一个生产链似的请求处理方式,其中最后的一个RequestProcessor就是FinalRequestProcessor,而正是在这个FinalRequestProcessor中,设置了Watch.

我们来看一下FinalRequestProcessor中的processRequest(Request request)部分的实现.

从这个方法中,我们可以这个一段代码块:

《ZooKeeper源码解析(10)-Watcher实现》

我们可以看到,其中调用了ZKDatabasegetData()方法来设置获取数据.并且最后有一个关于Watch的参数.

而我们上面正好介绍过,在使用getData()时,可以设置Watch

我们跟进去,可以发现它最后就是调用了DataTreegetData()方法.

《ZooKeeper源码解析(10)-Watcher实现》

我们可以看到,这儿只不过是记录了一下这个Watch

这里读者们可能就有一个疑问,就是,之前我们说过,ZooKeeper为每一个客户端维护一个Watch集合,但是这里我们只看到直接就放到了DataTree这一个共享的数据结构里了呀.

这是为什么呢?

因为Watch的实现NIOServerCnxn天生就是客户端独立的呀.

Watch是怎么被消费掉,怎么被触发的呢?

我们回到FinalRequestProcessorprocessRequest()方法,可以看到这么一段代码:

《ZooKeeper源码解析(10)-Watcher实现》

其中,最重要的就是图中我们圈出来的那一行.

我们看一下在zks.processTxn()的实现.

《ZooKeeper源码解析(10)-Watcher实现》

其中这个方法中,最重要的还是我们圈出来的那一行.

我们再跟进去,发现它调用了DataTreeprocessTxn()方法.我们直接来看这个方法的实现.

《ZooKeeper源码解析(10)-Watcher实现》

我们只分析OpCode.create时的情况.

我们看到,就是调用了createNode()方法.

在这个方法的尾部,我们可以看到,就触发了dataWatcheschildWatches

《ZooKeeper源码解析(10)-Watcher实现》

就这样完成了Watch的触发.


推荐阅读
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • Netty源代码分析服务器端启动ServerBootstrap初始化
    本文主要分析了Netty源代码中服务器端启动的过程,包括ServerBootstrap的初始化和相关参数的设置。通过分析NioEventLoopGroup、NioServerSocketChannel、ChannelOption.SO_BACKLOG等关键组件和选项的作用,深入理解Netty服务器端的启动过程。同时,还介绍了LoggingHandler的作用和使用方法,帮助读者更好地理解Netty源代码。 ... [详细]
  • 微软评估和规划(MAP)的工具包介绍及应用实验手册
    本文介绍了微软评估和规划(MAP)的工具包,该工具包是一个无代理工具,旨在简化和精简通过网络范围内的自动发现和评估IT基础设施在多个方案规划进程。工具包支持库存和使用用于SQL Server和Windows Server迁移评估,以及评估服务器的信息最广泛使用微软的技术。此外,工具包还提供了服务器虚拟化方案,以帮助识别未被充分利用的资源和硬件需要成功巩固服务器使用微软的Hyper - V技术规格。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 本文讨论了在使用PHP cURL发送POST请求时,请求体在node.js中没有定义的问题。作者尝试了多种解决方案,但仍然无法解决该问题。同时提供了当前PHP代码示例。 ... [详细]
  • 在IDEA中运行CAS服务器的配置方法
    本文介绍了在IDEA中运行CAS服务器的配置方法,包括下载CAS模板Overlay Template、解压并添加项目、配置tomcat、运行CAS服务器等步骤。通过本文的指导,读者可以轻松在IDEA中进行CAS服务器的运行和配置。 ... [详细]
  • ZooKeeper 学习
    前言相信大家对ZooKeeper应该不算陌生。但是你真的了解ZooKeeper是个什么东西吗?如果别人面试官让你给他讲讲ZooKeeper是个什么东西, ... [详细]
author-avatar
李冰或李冰圆_862
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有