Zookeeper迁移(扩容/缩容)

zookeeper选举原理

在迁移前有必要了解zookeeper的选举原理,以便更科学的迁移。

快速选举FastLeaderElection

zookeeper默认使用快速选举,在此重点了解快速选举:

  1. 向集群中的其他zookeeper建立连接,并且只有myid比对方大的连接才会被接受(也就是每2台只会有1个连接,避免连接浪费)

  2. 每台zookeeper默认先投自己,然后向集群广播自己的选票

  3. 收到对方的选票时,依次比较epoch(选举轮数)、zxid(事务id)、myid,较大者胜出,更新选票并广播

  4. 如果收到的选票中有某个节点超过集群半数,则胜出当选为leader,其他节点为follower

注意事项

  • zookeeper集群的数量应为奇数:

    因为根据paxos理论,只有集群中超过半数的节点还存活才能保证集群的一致性。假如目前集群有5个节点,我们最多允许2个节点不可用,因为3>5\2。当集群扩容到6个节点的时候,我们仍然只能最多允许2个节点不可用,到3个节点不可用时,将不满足paxos理论,因为3>6\2不成立。也就是说当集群节点数n为偶数时,其可用性与n-1是一样的,那我们何必多浪费一台机器呢?

  • 由于zookeeper只允许mid大的节点连接到mid小的节点,我们启动zookeeper的顺序应该按照myid小的到myid大的,最后再启动leader节点!

迁移目标

迁移过程中要保证原zookeeper集群还是能提供服务,新zookeeper集群同步老集群的数据,将zookeeper 域名指向新集群的3个节点,停掉老zookeeper集群。

相当于先扩容zookeeper,然后缩容zookeeper…

迁移步骤

原有zookeeper集群(server1、server2、server3)zoo.cfg配置如下:

1
2
3
4
5

# 省略其他配置
dataDir=/data
server.1=node1:2888:3888
server.2=node2:2888:3888
server.3=node3:2888:3888

使用命令:echo srvr | nc HOSTNAME 2181检查谁是leader({?}依次替换为1、2、3)

ps:也可以用echo stat | nc HOSTNAME 2181显示更详细信息

这里假设leader为node2.(按照正常情况,leader也理应是node2)

步骤1:新增节点4

  1. /data目录创建mid文件,内容为4

  2. 配置zoo.cfg,内容如下:

    1
    2
    3
    4
    5
    6

    # 省略其他配置
    dataDir=/data
    server.1=node1:2888:3888
    server.2=node2:2888:3888
    server.3=node3:2888:3888
    server.4=node4:2888:3888

  3. 启动zookeeper:{zookeeperDir}/bin/zkServer.sh start

  4. 检查所有节点是否提供服务,且集群中只有一个leader,例如以下命令:

    image2019-5-23_11-11-1.png?version=1&modificationDate=1558581062000&api=v2

可以看到Mode表示该节点的角色为leader。依次检查每一个节点,如果没有响应,或者出现多个leader,需要还原整个集群!

步骤2:新增节点5

  1. /data目录创建mid文件,内容为5

  2. 配置zoo.cfg,内容如下:

    1
    2
    3
    4
    5
    6
    7

    # 省略其他配置
    dataDir=/data
    server.1=node1:2888:3888
    server.2=node2:2888:3888
    server.3=node3:2888:3888
    server.4=node4:2888:3888
    server.5=node5:2888:3888

  3. 启动zookeeper:{zookeeperDir}/bin/zkServer.sh start

  4. 检查所有节点是否提供服务,且集群中只有一个leader:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...

步骤3:新增节点6

  1. /data目录创建mid文件,内容为6

  2. 配置zoo.cfg,内容如下:

    1
    2
    3
    4
    5
    6
    7
    8

    # 省略其他配置
    dataDir=/data
    server.1=node1:2888:3888
    server.2=node2:2888:3888
    server.3=node3:2888:3888
    server.4=node4:2888:3888
    server.5=node5:2888:3888
    server.6=node6:2888:3888

  3. 启动zookeeper:{zookeeperDir}/bin/zkServer.sh start

  4. 检查所有节点是否提供服务,且集群中只有一个leader:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...

步骤4:更新节点4

  1. 修改节点4的配置如下:

    1
    2
    3
    4
    5
    6
    7
    8

    # 省略其他配置
    dataDir=/data
    server.1=node1:2888:3888
    server.2=node2:2888:3888
    server.3=node3:2888:3888
    server.4=node4:2888:3888
    server.5=node5:2888:3888
    server.6=node6:2888:3888

  2. 重启节点4的zookeeper:{zookeeperDir}/bin/zkServer.sh restart

  3. 检查所有节点是否提供服务,且集群中只有一个leader:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...

步骤5:更新节点5

同步骤4

步骤6:更新老集群节点1

  1. 修改节点1的配置如下:

    1
    2
    3
    4
    5
    6
    7
    8

    # 省略其他配置
    dataDir=/data
    server.1=node1:2888:3888
    server.2=node2:2888:3888
    server.3=node3:2888:3888
    server.4=node4:2888:3888
    server.5=node5:2888:3888
    server.6=node6:2888:3888

  2. 重启节点4的zookeeper:{zookeeperDir}/bin/zkServer.sh restart

  3. 检查所有节点是否提供服务,且集群中只有一个leader:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...
    $ echo srvr | nc HOSTNAME 2181
    ...

步骤7:更新老集群节点3

同步骤6

步骤8:更新老集群节点2

最后更新leader节点:node2,同步骤6

ps:这时候如果没有读写zookeeper操作,集群的leader将变为节点6(因为节点6的myid最大)

步骤9:将原有zookeeper的url指向新的节点

修改域名解析,将zookeeper解析到新的3个节点上 (例如test1.zookeeper.com、test2.zookeeper.com、test3.zookeeper.com)指向node4,node5,node6

相关业务系统重启(避免缓存)

步骤10:老zookeeper集群下线

这一步需要等待所有的业务系统都重启之后。

这时候还是得一台一台关闭(下线),因为假如同时关闭HOSTNAME和node2,那当重启node3的时候集群将不可用(没有超过集群半数的节点存活)

步骤10.1:下线zookeeper老集群中的节点1

关闭HOSTNAME: {zookeeperDir}/bin/zkServer.sh stop

依次修改node2,3,4,5,6的配置,并且重启,配置如下:

1
2
3
4
5
6
7

# 省略其他配置
dataDir=/data
server.2=node2:2888:3888
server.3=node3:2888:3888
server.4=node4:2888:3888
server.5=node5:2888:3888
server.6=node6:2888:3888

重启后检查所有节点是否提供服务,且集群中只有一个leader。

ps:这时候如果没有读写zookeeper操作,leader将变成node5,因为node6节点重启的时候,集群重新选举,node5的myid最大

步骤10.2:下线zookeeper老集群中的节点2

关闭node2: {zookeeperDir}/bin/zkServer.sh stop

依次修改node3,4,5,6的配置,并且重启,配置如下:

1
2
3
4
5
6

# 省略其他配置
dataDir=/data
server.3=node3:2888:3888
server.4=node4:2888:3888
server.5=node5:2888:3888
server.6=node6:2888:3888

重启后检查所有节点是否提供服务,且集群中只有一个leader。

ps:这时候如果没有读写zookeeper操作,leader将重新变成node6

步骤10.3:下线zookeeper老集群中的节点3

关闭node3: {zookeeperDir}/bin/zkServer.sh stop

依次修改node4,5,6的配置,并且重启,配置如下:

1
2
3
4
5

# 省略其他配置
dataDir=/data
server.4=node4:2888:3888
server.5=node5:2888:3888
server.6=node6:2888:3888

重启后检查所有节点是否提供服务,且集群中只有一个leader。

ps:这时候如果没有读写zookeeper操作,node5将成为最终的leader

猜你喜欢

转载自blog.51cto.com/536410/2398911