服务端对于SetData请求的处理,大体可以分4大步骤,分别是请求的预处理、事务处理、事务应用和请求响应,如下图所示。


预处理

I/O层接收来自客户端的请求

判断是否是客户端“会话创建”请求

        ZooKeeper对于每一个客户端请求,都会检查是否是“会话创建”请求。然而对于SetData请求,因为此时已经完成了会话创建,因此按照正常的事务请求进行处理。

将请求交给ZooKeeper的PrepRequestProcessor处理器进行处理

创建请求事务头

会话检查

        客户端会话检查是指检查该会话是否有效,即是否已经超时。如果该会话已经超过,那么服务端就会向客户端抛出SessionExpiredException异常。

反序列化请求,并创建ChangeRecord记录

        面对客户端请求,ZooKeeper首先会将其进行反序列化并生成特定的SetDataRequest请求。SetDataRequest请求中通常包含了数据节点路径path、更新的数据内容data和期望的数据节点版本version。同时,根据请求中对应的path、ZooKeeper会生成一个ChangeRecord记录,并放入outstandingChanges队列中。

        outstandingChanges队列中存放了当前ZooKeeper服务器正在进行处理的事务请求,以便ZooKeeper在处理后续请求的过程中需要针对之前的客户端请求的相关处理。例如对于“会话关闭”请求来说,其需要根据当前正在处理的事务请求来收集需要清理的临时节点。

ACL检查

        由于当卡年请求是数据更新请求,因此ZooKeeper需要检查该客户端是否具有数据更新的权限。如果没有权限,那么会抛出NoAuthException异常。

数据版本检查

        如果ZooKeeper服务端发现当前数据内容的版本号与客户端预期的版本不匹配的话,那么将会抛出异常。

创建请求事务体SetDataTxn。

保存事务操作到outstandingChanges队列中去

事务处理

        对于事务请求,ZooKeeper服务端都会发起事务处理流程。无论对于会话创建请求还是SetData请求,或是其他事务请求,事务处理流程都是一致的,都是由ProposalRequestProcessor处理器发起,通过Sync、Proposal和Commit三个子流程相互协作完成的。

事务应用

交付给FinalRequestProcessor处理器

事务应用

        ZooKeeper会将请求事务头和事务体直接交给内存数据库ZKDatabase进行事务应用,同时返回ProcessTxnResult对象,包含了数据节点内容更新后的stat。

将事务请求放入队列:commitProposal

请求响应

统计处理

创建响应体SetDataResponse

        SetDataResponse是一个数据更新成功后的响应,主要包含了当前数据节点的最新状态stat。

创建响应头

        响应头是每个请求响应的基本信息,方便客户端对响应进行快速的解析,包括当前响应对应的事务ZXID和请求处理是否成功的标识err。

序列化响应

I/O层发送响应给客户端