加入收藏 | 设为首页 | 会员中心 | 我要投稿 济源站长网 (https://www.0391zz.cn/)- 数据工具、数据仓库、行业智能、CDN、运营!
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

很遗憾,没有一篇文章能讲清楚ZooKeeper

发布时间:2019-11-30 17:54:29 所属栏目:Windows 来源:站长网
导读:副标题#e# 【51CTO.com原创稿件】互联网时代是信息爆发的时代,信息的高并发催生了分布式系统的广泛应用。 图片来自 Pexels 作为分布式系统解决方案的 ZooKeeper,被广泛应用于多个分布式场景。例如:数据发布/订阅,负载均衡,命名服务,集群管理等等。 因

这里会通过 readResponse 方法统一处理:

很遗憾,没有一篇文章能讲清楚ZooKeeper


在 SendTread 接受到服务端的通知以后,会将事件通过 EventThread.queueEvent 发送给 EventThread。

正如前面提到的,在客户端注册时,已经将 Watcher 的具体内容保存在 ZKWatchManager 一样了。

所以,EventTread 通过 EventType 就可以知道哪个 Watcher 被响应了(数据变化了)。

然后从 ZKWatchManager 取出具体 Watch 放到 waitingEvent 队列等待处理。

最后,由 EventThread 中的 processEvent 方法依次处理数据更新的响应。

很遗憾,没有一篇文章能讲清楚ZooKeeper

版本(Version)

介绍完了 Watcher 机制,回头再来谈谈 ZNode 的版本(Version)。如果有一个客户端(ClientD),它尝试修改 C 的值,此时其他两个客户端会收到通知,并且进行后续的业务处理了。

很遗憾,没有一篇文章能讲清楚ZooKeeper

那么在分布式系统中,会出现这么一种情况:在 ClientD 对 C 进行写入操作的时候,又有一个 ClientE 也对 C 进行写入操作。这两个 Client 会去竞争 C 资源,通常这种情况需要对 C 进行加锁操作。

很遗憾,没有一篇文章能讲清楚ZooKeeper

两个 Client 竞争一个资源

因此引入 ZNode 版本(Version)概念。版本是用来保证分布式数据原子性操作的。

ZNode 的版本(Version)信息保存在 ZNode 的 Stat 对象中。有如下三种:

很遗憾,没有一篇文章能讲清楚ZooKeeper

本例只关注“数据节点内容的版本号”,也就是 Version。

如果说 ClientD 和 ClientE 对 C 进行写入操作视作是一个事务的话。在执行写入操作之前,两个事务分别会获取节点上的值,即节点保存的数据和节点的版本号(Version)。

以乐观锁为例,对数据的写入会分成以下三个阶段:数据读取,写入校验和数据写入。例如 C 上的数据是 1, Version 是 0。

此时 ClientD 和 ClientE 都获取了这些信息。假设 ClientD 先做写入操作,在做写入校验的时候,发现之前获得的 Version 和节点上的 Version 是相同的,都是 1,因此直接执行数据写入。

写入以后,Version 由原来的 1 变成了 2。当 ClientE 做写入校验时,发现自己持有的 Version=1 和节点当前的 Version=2,不一样。于是,写入失败,重新获取 Version 和节点数据,再次尝试写入。

除了上述方案以外,还可以利用 ZNode 的有序性。在 C 下面建立多个有序的子节点。每当一个 Client 准备写入数据的时候,创建一个临时有序的节点。

节点的顺序根据 FIFO 算法,保证先申请写入的 Client 排在其前面。每个节点都有一个序号,后面申请的节点按照序号依次递增。

很遗憾,没有一篇文章能讲清楚ZooKeeper

ClientD,ClientE 分别建立子 ZNode

每个 Client 在执行修改 C 操作的时候,都要检查有没有比自己序号小的节点,如果存在那么就进入等待。

直到比自己序号小的节点进行完毕以后,才轮到自己执行修改操作。从而保证了事物处理的顺序性。

会话(Session)

说完版本(Version)的概念,例子从原来的 ClientAB 已经扩充到了 ClientDE。这些客户端都会和 ZooKeeper 的服务端进行通信,或读取数据或修改数据。

我们将客户端与服务端完成的这种连接称为会话。ZooKeeper 的会话有 Connecting,Connected,Reconnecting,Reconnected 和 Close 这几种状态。

并且在服务端由专门的进程来管理他们,客户端初始化的时候就会根据配置自动连接服务器,从而建立会话,客户端连接服务器时会话处于 Connecting 状态。

一旦连接完成,就会进入 Connected 状态。如果出现延迟或者短暂失联,客户端会自动重连,Reconnecting 和 Reconnected 状态也就应运而生。

如果长时间超时,或者客户端断开服务器,ZooKeeper 会清理掉会话,以及该会话创建的临时数据节点,并且关闭和客户端的连接。

Session 作为会话实体,用来代表客户端会话,其包括 4 个属性:

SessionID,用来全局唯一识别会话。

TimeOut,会话超时事件。客户端在创造 Session 实例的时候,会设置一个会话超时的时间。

TickTime,下次会话超时时间点。后面“分桶策略”会用到。

isClosing,当服务端如果检测到会话超时失效了,会通过设置这个属性将会话关闭。

既然,会话是客户端与服务器之间的连接。在服务器端由 SessionTracker 管理会话。

SessionTracker 有一个工作就是,将超时的会话清除掉。于是“分桶策略”就登场了。

由于每个会话在生成的时候都会定义超时时间,通过当前时间+超时时间可以算出会话的过期时间。

由于 SessionTracker 不是实时监听会话超时,它是按照一定时间周期来监听的。

也就是说,如果没有到达 SessionTracker 的检查时间周期,即使有会话过期,SessionTracker 也不会去清除。由此,就引入会话超时计算公式,也就是 TickTime 的计算公式。

TickTime=((当前时间+会话过期时间)/检查时间间隔+1)*检查时间间隔。

将这个值计算出来以后,SessionTracker 会把对应的会话按照这个时间放在对应的时间轴上面。SessionTracker 在对应的 TickTime 检查会话是否过期。

(编辑:济源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读