什么是zxid
什么是zxid
什么是zxid,它是怎么产生的?
zxid 是 ZooKeeper 中一个事务的全局唯一 id,通过 zxid 描述各个事务之间的全序关系。
因此 zxid 就是客户端对数据进行一次变更所产生的事务在全局事务中的一个唯一 id。
zxid 的构成
zxid 是一个 64bits 的数,有两个部分组成:当前选举周期(epoch,占用高32bits)以及计数部分(counter,占用低32bits)。
epoch 表示 leader 关系的变化,每当新的集群产生新的leader,对于每一次选主操作,不管是什么原因导致的选主,epoch的值都会加一,也就是只要主节点变更,epoch的值就会不一样。
低32位的事务counter是指在当前主节点下事务变更的次数,比如update一个zk目录下的数据就会加一。
ZooKeeper 集群选主成功之后保证只会有一个Leader,并且此 Leader 的 epoch 是以前没有使用过的,这就保证了只会有一个 leader 使用本次选举过程中产生的 epoch,
在此基础上,每当客户端对数据进行变更的时候,leader 对产生的事务在当前 counter 的值加一产生新的事务的 zxid,并使用此 zxid 将此事务在集群中进行同步,这样就保证了事务的全序关系。
为什么 zxid 溢出需要重新选主
通过研究 zxid 的组成,可以发现,当单个 epoch 中处理的事务过多,以至于当前epoch 对应的 counter 数值超过了 32bits 计数的最大值,如果继续计数 epoch 就会 +1 ,
如果在未来,进行了一次选举,其他的 Server 当选了 leader,但是他产生的新 epoch 可能就会和现在 zxid 中的 epoch 重合,导致不同的事务会有相同的 zxid,破坏了事务之间的全序关系,可能导致脏数据的产生。
因此 ZooKeeper 在低 32 位达到最大计数值的时候,就会主动产生一次选主,避免以上问题 。
ZooKeeper 集群选主会产生什么影响
一般情况下使用 ZooKeeper 作为注册配置中心,集群选主对于客户端来说是无感知的,集群选主之后客户端会主动重连恢复。
但是对于依赖于 ZooKeeper Disconnected 事件的应用,可能会受到影响,在集群选主的时候,Server会向客户端返回 Disconnected 事件。
例如 Curator recipes 中 LeaderLatch 类型,在 ZooKeeper 集群选主的时候,LeaderLatch 会重新分配 Leader。
如何避免zookeeper zxid溢出问题
zxid的低32位的范围是42亿,也就是说如果某个整个zk集群很稳定,都没有发生重新选主的时间时, 如果此时对zk的变更事务比较频繁,比如不停的创建znode,设置znode数据等等,
如果这些时间的总和超过了42亿,那么就会发生zxid溢出而重新选主,重新选主之后高32位的epoch会加一,而事务counter会从0开始计数。
千万不要认为很难达到42亿的更新操作,简单的计算一下,如果每秒对zk有1000个事务操作的话,只需要50天左右就能导致zxid的溢出,
所以这里需要做好zxid的监控,在即将溢出时手动触发选主操作 是更好的方式。
zookeeper zxid溢出导致重新选主会导致session会话过期吗
一般来说,重新选主的时间都可以在几秒内完成,我们一般session的会话的过期时间一般都有10s左右。
所以正常情况下,zookeeper服务内部的重新选主操作是不会导致Session会话过期的。
zookeeper重启会导致session会话过期吗?
不会,因为zookeeper会定时保存内存数据的状态快照,其中包含了会话的对象信息sessionWithTimeOut字段的值,
这样zookeeper服务器重启之后会话id仍然存在,只要zookeeper重启的时间比较短,是不会导致session会话过期的 。