为什么ZooKeeper会出现zxid溢出?

本文介绍在使用ZooKeeper时,客户端出现zxid(Zookeeper事务ID)溢出的问题现象、问题原因和解决方案。

问题现象

ZooKeeper集群强制选主,并重置zxid低32位的计数值。

问题原因

zxid是一个长64位的数字。高32位用来表示当前Leader的周期,低32位用来表示当前请求产生的事务在当前Leader周期内的位置。每产生一个新的事务,zxid的低32位就会自动加1。当zxid达到最大值,即zxid的低32位达到0xffffffff,就会触发集群强制选主,并重置zxid低32位的计数值(zxid高32位变为新Leader的周期,低32位变为0)。

解决方案

目前,Server没有规避zxid溢出的方法,请在业务侧提前规避。

  • 对于使用ZooKeeper作为注册配置中心的使用场景:集群选主不会影响到正常使用,客户端在集群选主之后会自动重连恢复。

  • 对于依赖于客户端Disconnected事件的使用场景:例如,Curator Recipes中的LeaderLatch场景,在集群选主时,Server会产生Disconnected事件,表示Client与Server断开了连接。在选主完成之后,Client会通过重连机制重新连接到Server。

    在产生Disconnected事件后,LeaderLatch会重新选主(这里的选主是指使用LeaderLatch做集群选主的场景中,重新选择注册上来的其他实例作为主),此时可能会触发业务侧的一些其他逻辑。例如,在Flink 1.14及以下版本使用LeaderLatch作为选主的默认实现,在ZooKeeper集群选主时会导致Flink Job被重启。

在业务的实现中,可通过Curator Recipes中的LeaderSelector替换LeaderLatch的方法,对ZooKeeper短暂的断连做一定的容忍。