背景
事情源于一次生产的错误日志,某天早上突然收到错误日志激增的告警,登录日志系统查询发现这个错误日志 Session Expired事件有关,查询了下zk服务器的日志,发现有重新选主的日志,再具体看重新选主的原因是因为zxid溢出,当时天真的以为zxid溢出后导致重新选主会导致所有的Session会话过期?事实真的这样吗?
追究真相
我们首先来看一下zookeeper的事务id也就是zxid是怎么构成的,有什么作用。
- 事务zxid(总共64位)的构成是由epoch(高32位) + 事务counter(低32位)构成的,对于每一次选主操作,不管是什么原因导致的选主,epoch的值都会加一,也就是只要主节点变更,epoch的值就会不一样,低32位的事务counter是指在当前主节点下事务变更的次数,比如update一个zk目录下的数据就会加一
- 事务id的作用是为了保持变更事务的全序关系而记录的,有了这个事务id,我们就能知道两个不同时间之间的先后关系
好了,简单介绍了事务id的构成和作用,我们再回到问题本身上面来,zxid什么情况下会溢出呢?
我们知道zxid的低32位的范围是42亿,也就是说如果某个整个zk集群很稳定,都没有发生重新选主的时间时,如果此时对zk的变更事务比较频繁,比如不停的创建znode,设置znode数据等等,如果这些时间的总和超过了42亿,那么就会发生zxid溢出而重新选主,重新选主之后高32位的epoch会加一,而事务counter会从0开始计数。千万不要认为很难达到42亿的更新操作,简单的计算一下,如果每秒对zk有1000个事务操作的话,只需要50天左右就能导致zxid的溢出,所以这里我们需要做好zxid的监控,在即将溢出时手动触发选主操作是更好的方式。
那对于应用来说最关心的问题是: zookeeper服务器内部重新选主会导致session会话过期吗?
一般来说,重新选主的时间都可以在几秒内完成,我们一般session的会话的过期时间一般都有10s左右,所以正常情况下,zookeeper服务内部的重新选主操作是不会导致Session会话过期的。
此外,最后一个问题:zookeeper重启会导致session会话过期吗?
答案是不会,因为zookeeper会定时保存内存数据的状态快照,其中包含了会话的对象信息sessionWithTimeOut字段的值,这样zookeeper服务器重启之后会话id仍然存在,只要zookeeper重启的时间比较短,是不会导致session会话过期的。