Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

# 记录下 zookeeper 集群迁移和易错点

发表于 2022-05-29 分类于 java 阅读次数： 阅读次数： Disqus：

前阵子做了zk 的集群升级迁移，大概情况是原来是一个三节点的 zk 集群（最小可用
大概是

    zk1 192.168.2.1
    zk2 192.168.2.2
    zk3 192.168.2.3

在 zoo.cfg 中的配置就是如下

    server.1=192.168.2.1:2888:3888
    server.2=192.168.2.2:2888:3888
    server.3=192.168.2.3:2888:3888

## 加节点

需要将集群迁移到 192.168.2.4（简称 zk4），192.168.2.5（简称 zk5），192.168.2.6（简称 zk6） 这三台机器上，目前新的这三台机器上是没有 zk 部署的, 我们想要的是数据不丢失，那主要考虑的就是滚动升级，这里我其实犯了几个错误，也特别说明下
首先我们想要新的三台机器加进去，所以我在zk4，zk5，zk6 的配置是这样

    server.1=192.168.2.1:2888:3888
    server.2=192.168.2.2:2888:3888
    server.3=192.168.2.3:2888:3888
    server.4=192.168.2.4:2888:3888
    server.5=192.168.2.5:2888:3888
    server.6=192.168.2.6:2888:3888

这样起来发现状态是该节点没起来，
PS：查看当前节点状态可以通过 `./zkServer.sh status` 来查看
第一个问题是我需要一个`myid`文件，标识我是哪个节点，里面的内容就写 `4`或 `5` 或 `6` 这样就行了，并且这个文件的路径应该在配置文件中指定的`dataDir=`数据目录下
第二个问题是困扰我比较久的，我在按上面的配置启动节点后，发现这几个节点都是没起来的，并且有 `FastLeaderElection@xxx - Notification time out: 60000` 这个报错，一开始以为是网络不通，端口没开这些原因，检查了下都是通的，结果原因其实跟我之前的一个考虑是相关的，当有六个节点的时候，理论上需要有半数以上的节点可用，集群才会是健康的，但是按我这个方式起来，其实我配置了六个节点，但是其中三个都是不可用的（包括自身节点），那么它自然是没办法正常工作，所以这里其实也需要滚动添加，类似于这样
我的 `zk4` 的配置应该是这样

    server.1=192.168.2.1:2888:3888
    server.2=192.168.2.2:2888:3888
    server.3=192.168.2.3:2888:3888
    server.4=192.168.2.4:2888:3888

然后 `zk5` 的配置

    server.1=192.168.2.1:2888:3888
    server.2=192.168.2.2:2888:3888
    server.3=192.168.2.3:2888:3888
    server.4=192.168.2.4:2888:3888
    server.5=192.168.2.5:2888:3888

接着 `zk6` 的配置就可以是全部了

    server.1=192.168.2.1:2888:3888
    server.2=192.168.2.2:2888:3888
    server.3=192.168.2.3:2888:3888
    server.4=192.168.2.4:2888:3888
    server.5=192.168.2.5:2888:3888
    server.6=192.168.2.6:2888:3888

然后为了集群完全更新，就继续在 `zk4` 和 `zk5` 加上其他节点，这样我的 6 节点集群就起来了

## 下节点

这里我踩了另外一个坑，或者说没搞清楚两种方式的差别，

### 第一种

首先说说我没采用的第一种方式，（也是比较合理的）其实上面这个集群有个明显的问题，老集群其实还是各自认了一个三节点的集群，其中 zk3 是主节点，对于 zk1，zk2，zk3 来说它们能看到的就只有这三个节点，对于后三个 zk4，zk5，zk6 节点来说他们能连上其余五个节点，可以认为这是个六节点的集群，那么比较合理的操作应该是在老的三节点上把后面三个也都加进来，即每个节点的配置里 server 都有 6 个，然后我再对老的节点进行下线，这里下线需要注意的比较理想的是下一个节点就要修改配置，挪掉下线的节点后进行一遍重启，比如我知道了集群中的 leader 是在 zk3 上面，那么我先将 zk1 和 zk2 下掉，那么在我将 zk1 下线的之后，我将其他的五个节点都删除 zk1 的配置，然后重启，这样其实不是必须，但相对会可靠些，理论上我也可以在下掉 zk1 和 zk2 之后再修改配置重启其余节点。而当只剩下 zk3，zk4，zk5，zk6 四个节点的集群后，并且每个节点里的配置也只有这四个 server，我再下线 zk3 这个 leader 的时候，就会进行选举，再选出新的 leader，因为刚好是三节点，同样保证了最小可用。

### 第二种

这也是我踩坑的一种方式，就是我没有修改原来三节点的配置，并且我一开始以为可以通过下线 zk1，zk2，zk3（进行选举）的方式完成下线，然后再进行重启，但是这种方式就是我上面说的，原来的三节点里我下掉 zk1 还是能够正常运行，但是我下线 zk2 的时候，这个集群就等于是挂了，小于最小可用了，这样三节点都挂了，而且对于新加入的三个节点来说，又回到了最初起不来一样状态，六节点里只有三节点在线，导致整个集群都挂了，所以对于我这样的操作来说，我需要滚动修改启动，在下线 zk1 的时候就需要把 zk4，zk5，zk6 中的 zk1 移除后重启，当然这样唯一的好处就是可以少重启几个，同样继续下线 zk2 的时候，把 zk2 移除掉再重启，其实在移除 zk1 后修改重启后，在下线 zk2 的时候，集群就会重新选举了，因为 zk2 下线的时候，zk3 还是会一起下线。这个是我们需要特别注意的