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> 根据下次的超时时间,利用分桶策略管理会话的过期情况
会话的分桶管理策略:
- 每个会话都有下一次需要检测活性的时间
- 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发送请求。此时,由上面说的删除过程保证,不会发生会话转移。