背景
线上 flink 用户使用 ZooKeeper 做元数据中心以及集群选主,一些版本的flink在 ZooKeeper 选主时,会重启Job,导致一些非预期的业务损失。而ZooKeeper 在 zxid溢出时,会主动触发一次选主,就会导致flink Job的非预期重启,造成业务损失。本篇从原理和最佳实践上分析和解决由于ZooKeeper zxid 溢出导致的集群选主问题。检查ZooKeeper Server日志出现
zxid lower 32 bits have rolled over, forcing re-election, and therefore new epoch start
解决方法
ZooKeeper 本身提供当前处理的最大的Zxid,通过 stat 接口可查看到当前处理的最大的zxid的值,通过此值可以计算当前zxid距离溢出值还有多少差距。MSE 提供风险管理以及集群选主相关告警,提前预防和及时感知选主风险,避免业务损失
通过MSE ZooKeeper 风险管理和集群选主时间告警,预知风险
MSE ZooKeepr 提供风险管理的能力,风险管理会定期扫描集群风险,通知用户,zxid溢出就是集群的风险之一,当zxid接近溢出值之前,通过风险管理对风险的扫描,就可以看到集群zxid溢出的风险,提前做好规避。
风险管理会每天扫描集群的各项风险,也可以通过手动触发 一键健康检查进行集群风险诊断。
同时通过MSE ZooKeeper的集群选主时间告警,可以检测集群的选主时间,避免因为集群选主时间过长导致业务损失。通过告警管理中创建MSE 告警规则进行集群选主时间的告警设置
原因分析
什么是zxid,它是怎么产生的
首先我们了解一下什么是zxid,他是怎么产生的。zxid是ZooKeeper中一个事务的全局唯一id,通过zxid描述各个事务之间的全序关系。客户端对ZooKeeper内部数据的变更都是通过事务在 ZooKeeper 集群内的传播和处理完成的,因此zxid就是客户端对数据进行一次变更所产生的事务在全局事务中的一个唯一id,这个id描述了本次变更的事务在全局事务中的位置,并且不会有两个不同的事务拥有相同的zxid(全序关系)。
zxid是一个64bits的数,有两个部分组成:当前选举周期(epoch,占用高32bits)以及计数部分(counter,占用低32bits),epoch 表示 leader 关系的变化,每当新的集群产生新的leader,都会产生一个新的 epoch表示当前leader的选举周期,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。
运营活动
MSE Zookeeper相比开源自建性能高40%+,提供99.95% 稳定性保障,提供专业观测大盘、风险管理和推送轨迹等服务自治能力。新年特惠首购5折,赶紧抢购啦~