zookeeper 会话

事务:能改变zookeeper一致性的操作都是事务,比如添加节点、删除节点和更新数据等。
zk为每个事务分配一个唯一的zxid,用于标记事务的顺序。对于竞争,zk使用乐观锁的保证高效性。过程如下:

  • 获取znode的版本
  • 执行操作
  • 更新数据时,重新获取版本,并比对版本的序号,如果一致则执行更新

一个客户端会话包含4个核心的数据:

  • sessionId:会话唯一的ID
  • TimeOut:会话过期的时间
  • TickTime:下次检查客户端活性的时间
  • isClosing:客户端是否关闭的标记

会话管理

SessionTicker是管理会话的类,有3个核心的成员,分别是:

  • sessionById:HashMap<Long, SessionImpl> 管理会话的实体
  • sessionWithTimeOut:ConcurrentHashMap<Long, Integer> 包含了对话的过期时间,与内存数据库相通,与持久化快照文件有关
  • sessionSets: HashMap<Long, SessionSet> 根据下次的超时时间,利用分桶策略管理会话的过期情况

会话的分桶管理策略:

zookeeper随机监听端口 zookeeper会话_zookeeper

  • 每个会话都有下一次需要检测活性的时间
  • zk把相同时间需要检测活性的会话,放到一个桶中,如上图。
  • 到时间后,zk会统一检测一个桶中的会话活性
  • 如果会话未关闭,则重新计算新的时间,并把对应的会话转移进入新的桶。t/3是计算的活性时间

检测会话活性由Leader节点来处理

会话关闭

会话关闭发生在超时或者节点主动请求关闭的时候。

会话主要分成7个步骤,分别介绍:

  • 设置状态isClosing为True,不在接收该会话的任何新的请求
  • 集群发起关闭会话请求,其他服务同时也收到关闭的请求
  • 收集与该会话相关的临时节点,内存数据库中由对应的信息,但是会有两种特殊情况
  • 有删除节点请求:先执行删除,在统一删除其它的关联节点
  • 有临时创建节点的请求,创建,然后删除
  • 添加节点变更事务
  • 删除临时节点
  • 删除会话
  • NIOServerCxn删除对应的数据

会话重连

会话重连发生在客户端与服务器断开连接的时候,此时客户端会重连服务器。

重连有以下4个场景:

  • 超时时间内重连:服务器接受重连的客户端
  • 过期:不接受重连,需要建立新的会话
  • 失效:重连的时间太久了,比如网络慢的情况
  • 会话转移。

会话转移:假设集群有s1, s2, s3服务器,c1客户端发送请求r1到s1,但是网络太慢,导致客户端以为s1已经失去了连接,此时c1向s2发送请求r2,而且s2正常地执行了r2,此时发生了会话转移。

请求覆盖: r1最终到达了s1,导致集群执行r1,此时r1就覆盖了r2。

处理方案:每个服务求,都认为会话有自己的Owner,比如上面的c1的owner是s1。当s2收到r2时,判断owner不是自己,此时不执行请求。

想让s2执行r2,则需要c1与s1之间取消链接,集群同步后,方可与s2发送请求。此时,由上面说的删除过程保证,不会发生会话转移。