zookeeper - 写数据 - standAlone(5)

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 概述    了解完session建立过程以后,我们接下去应该了解的就是zookeeper的读写两个过程,这里的标题之所以增加standalone模式,是因为大家知道zookeeper在集群模式下的写入必须要考虑到数据的最终一致性过程,但是因为时间问题暂时只能对standAlone场景下的读写进行分析,这篇文章主要对于写进行分析。

概述

    了解完session建立过程以后,我们接下去应该了解的就是zookeeper的读写两个过程,这里的标题之所以增加standalone模式,是因为大家知道zookeeper在集群模式下的写入必须要考虑到数据的最终一致性过程,但是因为时间问题暂时只能对standAlone场景下的读写进行分析,这篇文章主要对于写进行分析。

    其实看过《zookeeper - session建立(4)》的情况下,对于这篇文章会看起来非常快,因为基本上写数据的过程在session的建立过程已经提交了,无非就是client端的报文发送过程、server端接收报文后的处理过程。

    client端的处理基本上没有什么特别的,server端我们按照 PrepRequestProcessor -> SyncRequestProcessor -> FinalRequestProcessor的数据流进行分析就可以了。逻辑其实也非常清晰的。

client-发送过程

    client端的处理逻辑其实非常简单,因为我们已经建立了session连接了,所以基本上就是发送报文三部曲:1、组装报文;2、发送报文;等待响应。这部分都比较简单,所以就直接贴源码解释了。


img_e5b6fcf96d0fd8eb93af8f174c7c21ff.png
报文组装

说明:

    发送报文的简单三部曲,依次是生成RequestHeader、生成CreateRequest、提交报文。


img_9d44b90d01febf29da970f35fe59ba5b.png
发送报文

说明:

    基本上就是发送报文的步骤,最后我们通过queuePacket将报文发送出去,并通过packet.wait()操作进入到等待时期。


img_edcbb984133f0754f75a3c8aa294b91c.png
发送的核心点

说明:

    基本上这里我们看到了packet被放入到了outgoingQueue当中,并唤醒sendThread进行数据发送,这里涉及了一个selector.wakeup的操作挺有意思,可以去网上搜下关键字。


img_210bb34346897d455a41105b53dc9c0c.png
sendThread执行发送过程

说明:

    基本上就是从outgoingQueue当中获取报文并发送出去,最后就是对于业务请求就会将package放置到pendingQueue当中。


server-接收过程

    最简单的模式就是standalone模式了(参考ZooKeeperServer类,没有实现replication)。下图展示了对应的流水线。它有3个request processor:PrepRequestProcessor,SyncRequestProcessor和FinalRequestProcessor。

img_3df37f9681b7e00d146abe7eae8ae4d9.png
standAlone下处理逻辑

    PrepRequestProcessor接收client的请求并执行,产生一个事务作为处理结果。执行一个操作后产生一个事务的处理结果,结果会直接反馈到ZK的data tree上。事务数据被附加到Request对象上。注意只有会改变ZK状态的操作才会产生一个事务,读操作不会产生事务,Request对象也不会附加事务数据。

    下一个request processor是SyncRequestProcessor。它负责持久化事务到磁盘上。本质上是把事务按照顺序append到事务日志上,并每隔一段时间产生快照。后面的文章会更详细讨论事务日志和快照。

    最后的processor是FinalRequestProcessor。当Request对象包括一个事务时它会改变data tree。另一方面,还会读data tree,返回结果给client。


img_f024c5a78f5ba7f0c5f9aec83083b7a7.png
server-1

说明:

    核心点在于readPlayload()进入server端的处理过程。


img_1be588d5d6cd487b29870821494853c2.png
server-2

说明:

    继续跟进readRequest()函数。


img_196514e0ec97ae7011179e0c4da45ab8.png
server-3

说明:

    开始提交任务,进入PrepRequestProcessor函数。


img_65395e0520da330d492bb60d9defb643.png
server-4

说明:

    具体进入提交任务,这里的firstProcessor就是PrepRequestProcessor,做的操作就是提交任务到submittedRequests当中。


img_352a75c9d2dc925aa8a7443df207b5f0.png
server-5

说明:

    PrepRequestProcessor开始进行处理,从这里开始看出来server端处理任务是一个个串行进行处理的。


img_923d6fae223538911b11b6f2a5c4bac7.png
server-6

说明:

    通过pRequest进一步跟进。


img_19e3adab24c4e0222148ed3078e0b80d.png
server-7

说明:

    创建事务的request对象,内部逻辑各个字段的意思没深入研究。


img_23d898c830228ecf61ffeb850a641959.png
server-8

说明:

    进入SyncRequestProcessor开始操作,将任务提交到queuedRequests队列当中。


img_c3f24c6eebef5c1bf189758694b34a78.png
server-9

说明:

    SyncRequestProcessor中通过queuedRequests当中取得任务bi9ng添加到toFlush开始操作,具体的就是flush操作。


img_e45b1e30062c17110f97d61e0679cb92.png
server-10

说明:

    这里将取得的任务提交到FinalRequestProcessor进行处理。


img_d180c5aeb61b46dedc33fa27ab987f1b.png
server-11

说明:

    进入本地的处理事务的逻辑当中。


img_75fcbf124fcd4cc5645569a7a76aefdb.png
server-12

说明:

    继续跟进创建事务对象。


img_c06a32bc04afec9ffbfe5632fbd1a3c4.png
server-13

说明:

    创建zookeeper的Node对象。


img_c16ed0518ffb91a309c8bcf47d2d786c.png
server-14

说明:

    创建dataNode并保存到dataTree对象当中,同时触发所有关联了这个path的watch事件。这里基本上包括触发当前path的所有事件,以及path对应的parentPath的child变更事件。


img_72ffd00b125787efff1c98ac1889530b.png
server-15

说明:

    这里将全面触发回调事件。


img_5980442d32f275542d5c5546f2b649ed.png
server-16

说明:

    通过io操作通知了client操作。


client-处理response过程

    整个处理响应报文的处理过程,我觉得需要关注的就是在发送报文的时候我们把报文放置到了pendingQueue当中,然后报文回的顺序和进入pendingQueue的顺序一致的,也就说server在处理报文的时候应该是串行的。

    还记得咱们发送完报文之后进入了package.wait方法,这里我们也看到通过notifyAll进行唤醒。

img_cc910660dd4e36338b0ffaaceafc7fc5.png
处理响应报文的入口

说明:

    这里是处理响应报文的入口函数


img_3f35ff3a7e2677ef63bb83523b221a2d.png
顺序处理响应报文

说明:

    这里是处理响应报文的整个过程,我们可以看到我们是先从pendingQueue当中获取了待响应的报文的,最后在finishPacket当中处理响应过程。


img_330668a0409e6cea1ca3459ca9c9d001.png
完成响应的处理

    说明:

        这里的过程其实主要是我们关注两个重点,一个没有callback的过程也就是我们不watch,另外一个是有callback的,就是我们开始watch。

        这里我增加一个单独的watch回调的段落进行讲解吧,这里只需要记住我们把package放入到eventThread当中了。


img_c703a0e5eda8a550a8abcb00e6604c80.png
处理回调事件

说明:

    核心的关键点在于理解整个zookeeper的回调事件具体的处理逻辑,后面会写一个watch的添加和回调过程,不过这里需要理解的就是watch是一次性触发的。

img_02ad76d5b78d4cd7022293dcafe6e4ec.png


参考文章

ZooKeeper学习之server端实现的基本骨架

ZooKeeper学习第六期---ZooKeeper机制架构

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
2月前
|
分布式计算 Java Hadoop
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
64 1
|
5月前
|
消息中间件 存储 Kafka
kafka 在 zookeeper 中保存的数据内容
kafka 在 zookeeper 中保存的数据内容
53 3
|
Java
分布式系列教程(24) -Zookeeper数据查看工具ZooInspector
分布式系列教程(24) -Zookeeper数据查看工具ZooInspector
111 0
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
|
7月前
|
Apache
Apache ZooKeeper - 构建ZooKeeper源码环境及StandAlone模式下的服务端和客户端启动
Apache ZooKeeper - 构建ZooKeeper源码环境及StandAlone模式下的服务端和客户端启动
129 2
|
7月前
|
存储 Java API
ZooKeeper【客户端的API操作、写数据流程】
ZooKeeper【客户端的API操作、写数据流程】
|
算法 Java 大数据
ZooKeeper 如何保证数据的一致性?【重要】
ZooKeeper 如何保证数据的一致性?【重要】
165 0
|
算法
Zookeeper 的读写机制、保证机制、Watcher(数据变更的通知)
Zookeeper 的读写机制、保证机制、Watcher(数据变更的通知)
157 0
|
存储
Zookeeper 数据模型和节点特性
Zookeeper 数据模型和节点特性
75 0
|
存储 监控 Apache
Apache ZooKeeper - ZK的数据和文件
Apache ZooKeeper - ZK的数据和文件
161 0
下一篇
无影云桌面