Zookeeper-连接和会话的过期清理策略(ExpiryQueue)

背景

Zookeeper作为一个服务器,需要管理与客户端的连接和会话,如接受连接,网络IO,和过期清理等,此文章就介绍下Zookeeper的过期策略.

注:目前网络上的资料介绍的都是会话的过期策略,在最新版Zookeeper中,将过期策略的代码抽象为ExpiryQueue类,除了会话,连接也用此类进行过期处理,但为了行文方便,下文中一律使用会话进行介绍
注:在下文中使用过期时间表示会话或连接何时过期,对应的英文为expiration time,用unix时间戳表示.超时时间表示会话或连接的超时时间,对应的英文为timeout,如5000ms

简单的会话清理策略

在介绍分桶策略之前,我先介绍一种比较简略的会话清理策略.

数据结构

使用3个TreeMap作为数据结构,如下:

  1. timeoutMap:其key是session,value是该会话的timeout(用于保存会话的timeout)
  2. elementMap:其key是session,value是该回话的过期时间(expiration time)(过期时间都是在当前时间之后的)
  3. expiryMap:其key是过期时间,value是原定在该过期时间过期的session

更新会话过期时间

客户端与服务端通信过程中更新上述3个数据结构,流程如下:

  1. 会话初始化时将其加入到timeoutMap,保存该会话的timeout
  2. 每当服务端与该会话进行通信时,更新会话的过期时间,将其过期时间修改为currentTime+timeout,包括2个步骤
    1. 通过elementMap获取该session的prevExpiryTime,根据prevExpiryTime在expiryMap删除其对应的session
    2. 修改elementMap,将session对应的过期时间修改为currentTime+timeout

清理过期会话

后台启动一个清理线程清理过期的session,线程中无限循环,执行工作如下:

  1. 执行定时的wait()操作,等待到当前时间为expiryMap中最小的key(使用TreeMap的原因),清理该key对应的session.

可能有同学对清理线程中执行的操作不是非常理解,由于expireMap的key是过期时间,当前时间到了过期时间,对应的session就要被清除.若在此之前,session与服务端进行了通信,就会更新expiryMap,删除该session原本的过期时间,该session就不会被清理线程清理.

优缺点

缺点:

  1. 若有多个session在同一时间过期,则exipryMap中只保存了最后一个调用put(time,session)方法的session的信息
    解决方案:将exipryMap的value修改为Set<Session>
  2. 若存在大量会话,则清理线程会在短时间内执行大量的wait()操作,虽然不知道会有什么不足,但总感觉有问题,比如系统能在短时间内调度大量的wait()操作吗?

优点:

  1. 实时性高

分桶策略

为了解决上述策略的缺点2,就引入了分桶策略,其将过期时间在某个时间段内的会话将看做一组,在每组最后的时间点,即下图中expiration time n,批量清理此组的过期会话.此时间段的长度可适当调整,若过大,则效率较高,实时性不足;若过小,则效率较低,实时性高.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值