2.ZooKeeper分桶策略实现高性能的会话管理「第五章 ZooKeeper 原理」「架构之路ZooKeeper理论和实战」

  

关历史文章(阅读本文前,您可能需要先看下之前的系列👇

国内最全的Spring Boot系列之四

享元模式:共享女友 - 第355篇

什么是 ZooKeeper - 第347篇

ZooKeeper安装 - 第348篇

ZooKeeper数据结构和实操  - 第349篇

ZooKeeper的watch机制 - 第350篇

ZooKeeper的acl权限控制  - 第351篇

ZooKeeper内存数据和持久化  - 第352篇

ZooKeeper集群搭建 - 第354篇

ZooKeeper Java客户端的基本使用 - 第356篇

ZooKeeper客户端Curator - 第358篇

ZooKeeper客户端Curator的进阶使用 - 第359篇

ZooKeeper客户端Curator实现Watch事件监听 - 第361篇

Spring Boot 使用 Curator 操作 ZooKeeper - 第363篇

Spring Boot使用Apache Curator实现服务的注册和发现 - 第364篇
Spring Boot使用Apache Curator实现分布式锁(可重入排它锁) - 第365篇

Spring Boot使用Apache Curator实现leader选举 - 第366篇

Spring Boot使用Apache Curator实现分布式计数器 - 367篇

ZooKeeper Session 基本原理 - 第369篇

ZooKeeper分桶策略实现高性能的会话管理 - 第371篇

ZooKeeper集群架构以及读写原理 - 第372篇

ZooKeeper Leader选举原理也不过如此,看完这篇你不再懵逼了 - 第374篇

Zookeeper 集群节点为什么要部署成奇数呢?- 第376篇

ZooKeeper集群脑裂问题 - 第379篇

分布式一致性算法Paxos,ZooKeeper的ZAB协议 - 第381篇

前言

         在前面的小节中,我们介绍了ZK的Session的基本原理,其中有一个属性是这么描述的:

TickTime:下次会话超时时间点,默认 2000 毫秒。可在 zoo.cfg 配置文件中配置,便于 server 端对 session 会话实行分桶策略管理。

         这里对Session会话实行分桶策略管理是什么意思呐?这就是本节要重点来介绍的。

一、分桶策略概述

1.1 什么是分桶策略

Zookeeper的session管理主要是通过SessionTracker来负责,其采用了分桶策略进行管理。

分桶策略是指,将空闲超时时间相近的会话放到同一个桶中来进行管理,以减少管理的复杂度。在检查超时时,只需要检查桶中剩下的会话即可,因为没有超时的会话已经被移出了桶,而桶中存在的会话就是超时的会话。

         zk 对于会话空闲的超时管理并非是精确的管理,即并非是一超时马上就执行相关的超时操作。

1.2 什么是分桶策略辅助理解

         通过分桶策略的定义,我们可以看出分桶策略中有两个桶,这两个桶在代码层面的表现形式就是两个Map数据类型,那么我们就会想Map的key是什么?接着往下看,我们慢慢就会揭开TA神奇的面纱。

二、分桶策略原理

2.1 分桶策略图示解说

那在每个红点所在的时间点都要运行一次‘session过期任务’,而且一次任务的执行,只使得一个session过期。这样效率不高。而且如果session比较多的话,那“session过期任务”的执行会占用很大的负载。

ZooKeeper为了方便管理session超时时间,使用分桶策略,使用如下计算公式,来计算session的超时时间:

long currentTime = Time.currentElapsedTime();
long sessionTimeout = 10000;
long expireTime_0 = currentTime + sessionTimeout;
long expireTime = (expireTime_0 / expirationInterval + 1) * expirationInterval;

此计算公式,会根据expirationInterval(默认2000毫秒)把时间分成相同时间段,让处于同一时间段的session的超时时间移动到此时间段结束的时间点上。

如上例子,这三个session的超时时间都变为ExpirationTime2。也就是在ExpirationTime1到ExpirationTime2之间的session,超时时间都设置为ExpirationTime2,这样当currentTime到达ExpirationTime2的时刻,执行一次session过期任务,就把这三个session都给设置为过期了。

         这样处理会更加方便。

2.2 分桶类ExpiryQueue整体工作流程图

 

2.2.1 ExpiryQueue作用

ZooKeeper服务端管理客户端会话超时使用到ExpiryQueue,用来管理Session超时的会话。

2.2.2 ExpiryQueue类图

 

该类中主要包含了以下变量:

(1)nextExpirationTime(下一个过期的时间点) ;

(2)expirationInterval(过期时间间隔) ;

(3)elemMap(Session对象集合,key是session对象,类型是SessionImpl,value为过期时间);

(4)expiryMap(过期的Session对象集合,key为过期时间,value为session)

        

该类中主要方法:

(1)构造方法初始化nextExpirationTime

(2)update增加或更新session的过期时间

(3)remove清除过期session

(4)getWaitTime判断当前时间是否已经超过了nextExpirationTime,超过返回0,没有超过返回nextExpirationTime-now,zookeeper中通过不停的轮询这个方法来判断是否清除过期session

(5)poll拉取过期session进行清除

2.2 分桶类ExpiryQueue数据结构理解

 

 

ExpiryQueue根据expirationInterval将时间分段,将每段区间的时间放入对应的一个集合进行管理。如图二所示,时间段在1503556830000-1503556860000中的数据将会放到1503556860000对应的集合中,1503556860000-1503556890000中的数据将会放到1503556890000的集合中,以此类推。

         在ExpiryQueue的数据结构中,图中的集合由ConcurrentHashMap<Long, Set<E>>进行管理,其中的Key值为到期时间。

         数据分段使用公式为:(当前时间(毫秒)/ expirationInterval + 1)* expirationInterval。该公式表示将当前时间按照expirationInterval间隔算份数,算完后再加一个份额,最后再乘以expirationInterval间隔,就得出了下一个到期时间。

三、分桶策略源码解析

         我们来看看源码的实现。

3.1 SessionTrackerImpl#touchSession

分桶策略的实现,主要是 SessionTrackerImpl#touchSession 方法,通俗说这个方法是给session续期的。我们先来阅读此方法的源码:

 

此代码的逻辑:

(1)调用touchSession(sessionId , timeout)方法,先从 sessionsById 这个map中通过 sessionId 取出session1(下面的update会此session1传入);

(2)然后调用updateSessionExpiry(s,timeout)进行续期。

         我们跟进updateSessionExpiry(s,timeout):

         从这里我可以看出来,session续期最终是交给了sessionExpiryQueue来进行管理,我们通过定义可以看到是ExpiryQueue<SessionImpl>,也是就是实现类是ExpiryQueue。

3.2 ExpiryQueue

         我们看下ExpiryQueue的update是怎么续期的。

         在此之前,我们先来看下ExpiryQuqueue类的情况:

 

(1)nextExpirationTime(下一个过期的时间点) ;

(2)expirationInterval(过期时间间隔) ;

(3)elemMap(Session对象集合,key是session对象,类型是SessionImpl,value为过期时间);

(4)expiryMap(过期的Session对象集合,key为过期时间,value为session)

3.3 ExpiryQueue#update

         对于ExpiryQueue有了基本的认知之后,我们就可以来看看update这个方法是怎么续期的了:

 

 

此代码逻辑说明:

(1)eleMap.get(elem):这个的E代表的是SessionImpl ,这个通过上面的说到的定义中ExpiryQueue<SessionImpl>可以看出来;所以这个就是通过会话对象获取到上一期的过期时间点。

(2)通过roundToNextInterval(time)计算下一个过期时间点:

(3)把session1 从expirationTime1 移动到 expirationTime2:(代码上就是先从expirationTime1的sessionSet中移除session1;然后把session1 添加到expirationTime2的sessionSet中。)

 

 

3.3 session过期任务线程

         过期任务主要是由SessionTrackerImpl的run来进行处理的:

在 SessionTrackerImpl 中的session超时任务中,只是把 session 的isClosing 变量设置为true。

只把session标识位isClosing是不够的,如果此session对应的client创建了临时节点,还需要把临时节点删掉呢。所以要调用 expirerexpire(s); 处理session过期逻辑的:

org.apache.zookeeper.server.ZooKeeperServer#createSessionTracker

         可以找到ZooKeeperServer的expire(Session): 

 

 

         此方法处理session过期逻辑:调用的是 ZooKeeperServer#close 方法,close方法中又调用了 ZooKeeperServer#submitRequest提交请求 方法,其中 操作类型为OpCode.closeSession。

         也就是 ZooKeeperServer 处理session 过期,是提交了一个操作类型为 为OpCode.closeSession的request,

3.4 session什么时候被移出掉呢?

         session标识位isClosing = true后,是在哪里把session从sessionSet中remove掉的呢?

以为 调用 expirer.expire(s); 就是为了把session从 sessionSet中remove掉。

所以的请求处理器,都只是把session 的isClosing赋值为true。

其实,在 touchSession()方法中有一个前提:就是session不能是isClosing 状态的,否则就直接返回:

 

四、小结

         这个可能有点复杂,大家可以根据源码自己进行分析的。

         要知道的核心就是:

(1)分桶策略的实现就是两个HashMap的容器来进行实现的。

(2)核心的两个方法就是SessionTrackerImpl的touchSession()和run()方法。 

 

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。

à悟空学院:悟空学院

学院中有Spring Boot相关的课程!!

SpringBoot视频:从零开始学Spring Boot Plus - 网易云课堂

SpringBoot交流平台:https://t.cn/R3QDhU0

SpringSecurity5.0视频:权限管理spring security - 网易云课堂

ShardingJDBC分库分表:分库分表Sharding-JDBC实战 - 网易云课堂

分布式事务解决方案:分布式事务解决方案「手写代码」 - 网易云课堂

JVM内存模型调优实战:深入理解JVM内存模型/调优实战 - 网易云课堂

Spring入门到精通:Spring零基础从入门到精通 - 网易云课堂

大话设计模式之爱你:大话设计模式之爱你一万年 - 网易云课堂

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟纤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值