zookeeper原理篇-Zookeeper会话机制,面试阿里P7岗

本文深入解析Zookeeper中SessionID的生成算法,涉及时间毫秒值、位移操作以及机器码ID的组合。同时,介绍了SessionTracker如何管理会话,包括创建、激活和清理过程,强调了分桶策略在会话超时检查中的作用,以及会话激活的步骤。此外,文章还讨论了防止SessionID生成负数的解决方案。
摘要由CSDN通过智能技术生成
 nextSid = (System .currentTim eM illis() « 24) » 8;
nextSid = nextSid | (id « 5 6 );
return nextSid;

} }


从这段代码,我们可以看到session的创建大概分为以下几个步骤:

**1.获取当前时间的毫秒表示**

我们假设当前System.currentTimeMills()获取的值是1380895182327,其64位二进制表示为:

00000000 00000000 00000001 01000001 10000011 11000100 01001101  11110111

2. **接下来左移24位**,我们可以得到结果:

01000001 100000011  11000100  01001101  11110111 00000000 00000000 00000000,可以看到低位已经把高位补齐,剩下的低位都使用了0补齐

**3.右移8位**,结果变成了:

00000000 01000001 100000011  11000100  01001101  11110111 00000000 00000000

**4.计算机器码标识ID**:

在initializeNextSession方法中,出现了一个id变量,这个变量就是生成的SID的值,而SID在部署的时候就是我们在myid中配置的值,一般是一个整数,假设此时的值为2,转为64位二进制表示:

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010

此时发现高位几乎都是0,进行左移56位以后,得到值如下:

00000010 00000000 00000000 00000000 00000000 00000000 00000000 00000000

**5.将前面第三步和第四步得到的结果进行 | 操作**:

可以得到结果为:

00000010 01000001 10000011 11000100 01001101 11110111 00000000 00000000

这个时候我们可以得到一个单机中唯一的序列号ID,整个算法大概可以理解为,先通过高8位确定机器以后,后面的56位按照毫秒进行随机,可以看出来当前的算法!还是蛮严谨的,基本上看不出来什么明显的问题,但是其实也有问题的,其中我们可以看到,zk选择了当前机器时间内的毫秒作为基数,但是如果时间到了2022年4月8号以后, System .  currentTimeMillis ()的值会是多少呢?

```java
Date d =  new Date (2022-1900 f 3,8);
System. out. p rin tln ( Long. toBinaryString(d .getTime()));

打印出来的结果为:

0000000000000000000000011000000000000100110000010000010000000000

接着我们左移24位以后会发现,这个时候的值依然是个负数,所以我们为了保证不会出现负数的情况,解决方案如下:

public static long initializeNextSession(long id { ) {
long nextSid = 0;
nextSid = (System .currentTim eM illis() « 24) > » 8;
nextSid = nextSid | (id « 5 6 );
return nextSid;
} }

这样就可以避免生成的时候出现负数了

SessionTracker

SessionTracker是Zookeeper中的会话管理器,负责整个zk生命周期中会话的创建管理清理操作,而每一个会话在Sessiontracker内部都保留了三份,大体如下:

1.sessionsWithTimeout这是一个ConcurrentHashMap<Long,Integer>类型的数据结构,用来管理会话的超时时间,这个参数会被持久化到快照文件中去

2.sessionsById是一个HashMap<Long,Integer>类型的数据结构,用于根据sessionId来管理session实体

3.sessionsSets同样也是一个HashMap<Long,Integer>类型的数据结构,用来会话超时的时候进行归档,便于进行会话恢复和管理

会话创建

创建会话的过程,大体可以分为几个步骤,分别是处理ConnectRequest请求、创建会话、处理器链路处理和响应,在zk服务端中,首先是NIOServerCnxn来负责接受来自客户端的会话创建请求,并且进行反序列化工作,然后开始分配超时时间。分配完毕后,会开始创建sessionId,并且将其注册到SessionsById和sessionsWithTimeOut,进行激活,这个时候就可以考虑处理流转。

会话管理

Zookeeper中的会话管理主要是SesssionTracker负责的,内部使用了一个特殊的机制,称之为分桶策略,所谓分桶策略,其实是将类似的会话放在一个区块中进行管理,以便于zookeeper对会话进行不同区块的隔离以及同一区块的统一处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xwsvYD3g-1630587938757)(assets/1589464633427.png)]

从图中我们可以看到,所有的会话都分配在了不同的区块中,分配原则是每个会话的下个超时的时间点,ExpiractionTime是指最近一次可能过期的时间点,每一个会话的ExpiractionTime的计算方式如下:

ExpiractionTime = CurrentTime + SessionTimeout

但是不要忘记了,Zookeeper的Leader服务器在运行期间会定期检查是否超时,这个定期的时间间隔为ExpiractionInterval,单位是秒,默认情况下是tickTime的值,即2000毫秒进行一次检查,完整的ExpiractionTime的计算方式如下:

ExpirationTime_  = CurrentTime + SessionTimeout ;
ExpirationTime =  (ExpirationTime_ / Expirationlnterval+ 1) x Expirationlnterval ;
会话激活

同样的,在整个zookeeper运行过程中,客户端会在超时时间内向服务端发送PING请求来保持时效性,俗称心跳检测,而服务端在接受到了客户端的心跳请求后需要再次激活会话状态,这个过程称之为TouchSession,流程如下:

1.检验会话是否已经被关闭,Leader会去检查会话是否被关闭,如果已经关闭,不会再去激活该会话

2.如果会话没有被关闭,则开始计算下一次的超时时间Expiration_New,而计算的过程则是使用上面的公式

3.计算完新的超时时间以后,会去获取会员原来的超时时间,并且根据时间来定位原来存放的区块

4.接着,从该区块中找到会话,进行会话迁移,放入新的Expiration_New对应的区块中,如图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t9UEHOrr-1630587938759)(assets/1589728495374.png)]

经过以上的步骤,基本已经完成了会话的激活,而每一次心跳的检测,则是进行了一次会话激活操作,在整个Zookeeper运行过程中,一般如下两个操作才会导致会话激活:

1.当客户端向服务端发送请求的时候,包括读写请求,都会主动触发一次会话激活

2.如果客户端在sessionTimeOut / 3时间范围内尚未和服务器之间进行通信,即没有发送任何请求,就会主动发起一个PING请求,去触发服务端的会话激活操作

除此之外,由于会话之间的激活是按照分桶策略进行保存的,因此我们可以利用此策略优化对于会话的超时检查,在Zookeeper中,会话超时检查也是由SessionTracker负责的,内部有一个线程专门进行会话的超时检查,只要依次的对每一个区块的会话进行检查,由于分桶是按照ExpriationInterval 的倍数来进行会话分布的,因此只要在这些时间点检查即可,这样可以减少检查的次数,并且批量清理会话,实现较高的效率。

会话清理

会话检查操作以后,当发现有超时的会话的时候,会进行会话清理操作,而Zookeeper中的会话清理操作,主要是以下几个步骤:

结语

看到这篇文章的人不知道有多少是和我一样的Android程序员。

35岁,这是我们这个行业普遍的失业高发阶段,这种情况下如果还不提升自己的技能,进阶发展,我想,很可能就是本行业的职业生涯的终点了。

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

我们要有危机意识,切莫等到一切都成定局时才开始追悔莫及。只要有规划的,有系统地学习,进阶提升自己并不难,给自己多充一点电,你才能走的更远。

千里之行始于足下。这是上小学时,那种一元钱一个的日记本上每一页下面都印刷有的一句话,当时只觉得这句话很短,后来渐渐长大才慢慢明白这句话的真正的含义。

有了学习的想法就赶快行动起来吧,不要被其他的事情牵绊住了前行的脚步。不要等到裁员时才开始担忧,不要等到面试前一晚才开始紧张,不要等到35岁甚至更晚才开始想起来要学习要进阶。

最后免费分享给大家一份系统的Android学习进阶资料,希望这份资料可以给大家提供帮助。
习的想法就赶快行动起来吧,不要被其他的事情牵绊住了前行的脚步。不要等到裁员时才开始担忧,不要等到面试前一晚才开始紧张,不要等到35岁甚至更晚才开始想起来要学习要进阶。

最后免费分享给大家一份系统的Android学习进阶资料,希望这份资料可以给大家提供帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值