最近由于业务需求,测试各种组件的高可用性。由于我们的环境在AWS 北京部署。只有两个Aviable Zone(可用区)。

注释:有两个数据中心,相互需要做容灾的需求,和本文测试的情况是相同的。

而Zookeeper需要3个以上的单数节点同时工作,并且,必须保证半数以上的节点存活,还能正常提供服务。

那么,针对只有两个AZ的情况,不管怎么规划,都有概率遇到存在半数以上的AZ挂掉,导致整个Zookeeper不可用的情况。

所以,我们能做的就是,在这个AZ挂掉之后,我们怎么尽快处理,并恢复环境。

我们准备两个软件安装好,参数配置好的机器。在可用区1完全挂掉之后,可以手动启动两个备用节点。将可用区2的Zookeeper数量增加过半数。就可以在可用区2恢复Zookeeper的服务。

参考下图:

以上的设想,是否能实现呢?

那我们今天就来测试一下。

1. 一共准备了5台机器,作为测试

2. Zookeeper的下载与安装。

2.1 Zookeeper官方下载地址

https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/

2.2 下载软件

wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz

2.3 详细Zookeeper安装步骤,请参考:

https://blog.51cto.com/hsbxxl/1971241

2.4 zoo.cfg的配置 #cat zoo.cfg

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/log
clientPort=2181
autopurge.snapRetainCount=3
autopurge.purgeInterval=6
server.1=172.31.9.73:2888:3888
server.2=172.31.20.233:2888:3888
server.3=172.31.26.111:2888:3888
server.4=172.31.17.68:2888:3888
server.5=172.31.16.33:2888:3888

2.5  根据zoo.cfg创建data和log两个文件夹

mkdir -p /data/zookeeper/data
mkdir -p /data/zookeeper/log

2.6 根据节点号码,修改文件

echo 1 > /data/zookeeper/data/myid

3. 一共准备了5台EC2进行测试,并且都已经安装好Zookeeper

但是只启动三台,另两个机器作为standby

下图可以看到,已经有三台启动zookeeper,

注意,在Zookeeper启动的过程中,必须保证三台及以上,zookeeper集群才能正常工作

4. 接下来,我开始逐个机器关机,看zookeeper的状态

当前leader在zk3上,我们先关闭zk1,再关闭zk3,看Leader会不会飘到zk2上

4.1 在zk1上执行kill,杀掉进程

[root@ip-172-31-9-73 ~]# jps
12438 Jps
7545 QuorumPeerMain
[root@ip-172-31-9-73 ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /root/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: follower
[root@ip-172-31-9-73 ~]# kill -9 7545

4.2 在zk5上通过zkCli链接zk3,并可以查询数据。

在zk1上kill掉进程之后,理论上,还有zk2和zk3存活,但是zkCli的连接显示已经报错。

[root@ip-172-31-16-33 bin]# ./zkCli.sh -server 172.31.26.111:2181
Connecting to 172.31.26.111:2181
......
[zk: 172.31.26.111:2181(CONNECTED) 0] ls /
[zk-permanent, zookeeper, test]
[zk: 172.31.26.111:2181(CONNECTED) 1] 2019-06-23 07:28:06,581 [myid:] - INFO  [main-SendThread(ip-172-31-26-111.cn-north-1.compute.internal:2181):ClientCnxn$SendThread@1158] - Unable to read additional data from server sessionid 0x30000c504530000, likely server has closed socket, closing socket connection and attempting reconnect
......
2019-06-23 07:28:09,822 [myid:] - INFO  [main-SendThread(ip-172-31-26-111.cn-north-1.compute.internal:2181):ClientCnxn$SendThread@1025] - Opening socket connection to server ip-172-31-26-111.cn-north-1.compute.internal/172.31.26.111:2181. Will not attempt to authenticate using SASL (unknown error)
2019-06-23 07:28:09,824 [myid:] - INFO  [main-SendThread(ip-172-31-26-111.cn-north-1.compute.internal:2181):ClientCnxn$SendThread@879] - Socket connection established to ip-172-31-26-111.cn-north-1.compute.internal/172.31.26.111:2181, initiating session
2019-06-23 07:28:09,825 [myid:] - INFO  [main-SendThread(ip-172-31-26-111.cn-north-1.compute.internal:2181):ClientCnxn$SendThread@1158] - Unable to read additional data from server sessionid 0x30000c504530000, likely server has closed socket, closing socket connection and attempting reconnect

4.3 我们继续 kill掉zk3上的进程,只保留zk2上的进程。但是我们已经无法确认zk2是Leader还是Follow,或者说,他是否还保留有数据。

[root@ip-172-31-26-111 bin]# jps
4183 QuorumPeerMain
4648 Jps
[root@ip-172-31-26-111 bin]# kill -9 4183
[root@ip-172-31-26-111 bin]# jps
4658 Jps

4.4 zk3上进程kill掉之后,链接就不只是上面的报错了,而是直接连接拒绝

[root@ip-172-31-16-33 bin]# ./zkCli.sh -server 172.31.26.111:2181
Connecting to 172.31.26.111:2181
......
Welcome to ZooKeeper!
2019-06-23 07:35:18,411 [myid:] - INFO  [main-SendThread(ip-172-31-26-111.cn-north-1.compute.internal:2181):ClientCnxn$SendThread@1025] - Opening socket connection to server ip-172-31-26-111.cn-north-1.compute.internal/172.31.26.111:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2019-06-23 07:35:18,533 [myid:] - INFO  [main-SendThread(ip-172-31-26-111.cn-north-1.compute.internal:2181):ClientCnxn$SendThread@1162] - Socket error occurred: ip-172-31-26-111.cn-north-1.compute.internal/172.31.26.111:2181: Connection refused
[zk: 172.31.26.111:2181(CONNECTING) 0] 2019-06-23 07:35:19,639 [myid:] - INFO  [main-SendThread(ip-172-31-26-111.cn-north-1.compute.internal:2181):ClientCnxn$SendThread@1025] - Opening socket connection to server ip-172-31-26-111.cn-north-1.compute.internal/172.31.26.111:2181. Will not attempt to authenticate using SASL (unknown error)
2019-06-23 07:35:19,640 [myid:] - INFO  [main-SendThread(ip-172-31-26-111.cn-north-1.compute.internal:2181):ClientCnxn$SendThread@1162] - Socket error occurred: ip-172-31-26-111.cn-north-1.compute.internal/172.31.26.111:2181: Connection refused

4.5 可以看到zk2上的进程还在,

# jps
5155 QuorumPeerMain
5211 Jps

4.6 并且通过下面命令,可以检查到zk2 的2181端口还在提供服务

# echo ruok | nc localhost 2181
imok

4.7 但是其他命令是没有正常输出的,只有echo ruok | nc localhost 2181输出ok。

# echo ruok | nc 172.31.16.33 2181
imok[root@ip-172-31-16-33 bin]# echo conf | nc 172.31.16.33 2181
This ZooKeeper instance is not currently serving requests
# echo dump | nc 172.31.16.33 2181
This ZooKeeper instance is not currently serving requests

4.8  ZooKeeper 四字命令

ZooKeeper 四字命令

功能描述

conf

输出相关服务配置的详细信息。

cons

列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。包括“接受 / 发送”的包数量、会话 id 、操作延迟、最后的操作执行等等信息。

dump

列出未经处理的会话和临时节点。

envi

输出关于服务环境的详细信息(区别于 conf 命令)。

reqs

列出未经处理的请求

ruok

测试服务是否处于正确状态。如果确实如此,那么服务返回“imok ”,否则不做任何相应。

stat

输出关于性能和连接的客户端的列表。

wchs

列出服务器 watch 的详细信息。

wchc

通过 session 列出服务器 watch 的详细信息,它的输出是一个与watch 相关的会话的列表。

wchp

通过路径列出服务器 watch 的详细信息。它输出一个与 session相关的路径。

4.9 正常情况下,以上命令可以输出:

# echo dump | nc 172.31.20.233 2181

SessionTracker dump:
org.apache.zookeeper.server.quorum.LearnerSessionTracker@77714302
ephemeral nodes dump:
Sessions with Ephemerals (0):

# echo conf | nc 172.31.20.233 2181

clientPort=2181
dataDir=/data/zookeeper/data/version-2
dataLogDir=/data/zookeeper/log/version-2
tickTime=2000
maxClientCnxns=60
minSessionTimeout=4000
maxSessionTimeout=40000
serverId=2
initLimit=10
syncLimit=5
electionAlg=3
electionPort=3888
quorumPort=2888
peerType=0

# echo envi| nc 172.31.20.233 2181

Environment:
zookeeper.version=3.4.14-4c25d480e66aadd371de8bd2fd8da255ac140bcf, built on 03/06/2019 16:18 GMT
host.name=ip-172-31-20-233.cn-north-1.compute.internal
java.version=1.8.0_212
java.vendor=Oracle Corporation
java.home=/usr/java/jdk1.8.0_212-amd64/jre
java.class.path=/root/zookeeper-3.4.14/bin/../zookeeper-server/target/classes:/root/zookeeper-3.4.14/bin/../build/classes:/root/zookeeper-3.4.14/bin/../zookeeper-server/target/lib/*.jar:/root/zookeeper-3.4.14/bin/../build/lib/*.jar:/root/zookeeper-3.4.14/bin/../lib/slf4j-log4j12-1.7.25.jar:/root/zookeeper-3.4.14/bin/../lib/slf4j-api-1.7.25.jar:/root/zookeeper-3.4.14/bin/../lib/netty-3.10.6.Final.jar:/root/zookeeper-3.4.14/bin/../lib/log4j-1.2.17.jar:/root/zookeeper-3.4.14/bin/../lib/jline-0.9.94.jar:/root/zookeeper-3.4.14/bin/../lib/audience-annotations-0.5.0.jar:/root/zookeeper-3.4.14/bin/../zookeeper-3.4.14.jar:/root/zookeeper-3.4.14/bin/../zookeeper-server/src/main/resources/lib/*.jar:/root/zookeeper-3.4.14/bin/../conf:
java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.io.tmpdir=/tmp
java.compiler=<NA>
os.name=Linux
os.arch=amd64
os.version=4.14.123-86.109.amzn1.x86_64
user.name=root
user.home=/root
user.dir=/root/zookeeper-3.4.14/bin

5. 这个时候,我去启动另外两个备用节点,zk4,zk5.这个两个节点都是第一次启动。

6. 再次连接到zookeeper上,可以看到,至少数据还是没有丢失的

[root@ip-172-31-16-33 bin]# ./zkCli.sh -server 172.31.16.33:2181
Connecting to 172.31.16.33:2181
......
[zk: 172.31.16.33:2181(CONNECTED) 0] ls /
[zk-permanent, zookeeper, test]

7. 通过以上测试,似乎是达到我们预期的结果。唯一的一点小问题,就是:我们有3个节点,为什么关闭1个,剩余两个,就不能正常运行了呢?

其实,这里是有个“想当然”的小问题。

我们以为,只启动三个. 其实,Zookeeper集群,识别的是5个, 为什么呢?

Zookeeper靠什么去识别集群中有几个节点呢?当然不是靠“想当然”。一定是有配置文件告诉它。Zookeeper,只有两个配置文件zoo.cfg和myid。

那就只有zoo.cfg会影响到它了。

8. 我将zoo.cfg做如下修改之后。只开启3个节点,在关闭一个节点之后,还是可以正常运行的。

注释掉server2和server5

# cat zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/log
clientPort=2181
autopurge.snapRetainCount=3
autopurge.purgeInterval=6
server.1=172.31.9.73:2888:3888
#server.2=172.31.20.233:2888:3888
server.3=172.31.26.111:2888:3888
server.4=172.31.17.68:2888:3888
#server.5=172.31.16.33:2888:3888

9. 关闭server4之后,还有server2和server3活着。

[root@ip-172-31-26-111 ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /root/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: leader
[root@ip-172-31-9-73 ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /root/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: follower

10. 总结,如果考虑两个AZ的情况下,zookeeper节点数多的AZ出现灾难情况,我们如何快速恢复?

(假设Server1/Server2在1AZ,Server3/Server4/Server5在2AZ)

10.1. 在Zookeeper节点少的AZ,多准备2台配置好zookeeper的EC2,并关机待使用。Server4/Server5具体zoo.cfg配置如下

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/log
clientPort=2181
autopurge.snapRetainCount=3
autopurge.purgeInterval=6
server.3=172.31.26.111:2888:3888
server.4=172.31.17.68:2888:3888
server.5=172.31.16.33:2888:3888

10.2.  Server1/Server2/Server3,是正常运行的节点,配置如下:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/log
clientPort=2181
autopurge.snapRetainCount=3
autopurge.purgeInterval=6
server.1=172.31.9.73:2888:3888
server.2=172.31.20.233:2888:3888
server.3=172.31.26.111:2888:3888

10.3.  灾难发生,Server1/Server2所在的1AZ挂掉的情况下,需要人工介入,将Server3的配置更改为如下配置,并重启Server3的zookeeper服务,然后启动Server4/Server5,一定要先启动Server3,注意顺序。

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/log
clientPort=2181
autopurge.snapRetainCount=3
autopurge.purgeInterval=6
server.3=172.31.26.111:2888:3888
server.4=172.31.17.68:2888:3888
server.5=172.31.16.33:2888:3888

10.4 日常运行状态

10.5 检查已经创建的znode信息

./zkCli.sh -server 172.31.16.33:2181 ls /
Connecting to 172.31.16.33:2181
[zk-permanent, zookeeper, test]

10.6 关闭Server1/Server2,注意顺序,先关闭follow,如果先关闭leader,会发生切换。我们期望的是Server3最后以follow的身份存活。

11. 最终可以看到测试结果,一切都是按照我们“想当然”的方向发展。

12. 最后验证zookeeper中的znode数据,还是都存在的。

./zkCli.sh  -server 172.31.16.33:2181 ls /
Connecting to 172.31.16.33:2181
[zk-permanent, zookeeper, test]

13. 其实数据一直是在这个路径下,只要有一个节点还保留,就会保存下去。

# ls /data/zookeeper/data/
myid  version-2  zookeeper_server.pid

注意:一定要保证Server4/Server5的下面两个路径是空的,不然会出现,Server4/Server5识别的是之前的陈旧信息。

/data/zookeeper/data/version-2
/data/zookeeper/log/version-2

14. 说到这里,我们可以理解到,Zookeeper的全部数据,都是存放在下面两个路径中。如果需要做备份,可以直接在OS层面,做cp备份即可。

dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/log

衍生一个想法,就是如果想做跨Region,北京(主环境)到宁夏(容灾环境)的zookeeper的高可用怎么做呢?

我们可以考虑将北京的zookeeper的数据文件定期备份,并导入到宁夏的环境。

具体步骤:

<1. 在宁夏启动一个Zookeeper集群,并配置好,然后关闭zookeeper服务,清空掉数据文件夹。

<2. 在北京,通过脚本定期检查zookeeper各个节点状态,从一个运行健康的节点,定期备份数据到S3的一个bucket,为每个文件加上时间戳。

<3. 通过S3的Cross Region Replication,同步到宁夏。

<4. 然后在宁夏,从S3读取备份文件,并还原到灾备的zookeeper中。

Zookeeper 跨区高可用方案相关推荐

  1. 注册不上zookeeper无报错_Zookeeper 跨区高可用方案

    最近由于业务需求,测试各种组件的高可用性.由于我们的环境在AWS 北京部署.只有两个Aviable Zone(可用区). 注释:有两个数据中心,相互需要做容灾的需求,和本文测试的情况是相同的. 而Zo ...

  2. MySQL数据库的高可用方案总结

    高可用架构对于互联网服务基本是标配,无论是应用服务还是数据库服务都需要做到高可用.虽然互联网服务号称7*24小时不间断服务,但多多少少有一些时候服务不可用,比如某些时候网页打不开,百度不能搜索或者无法 ...

  3. HDFS——HDFS+Zookeeper搭建高可用HDFS

    2019独角兽企业重金招聘Python工程师标准>>> 问题说明 NameNode是HDFS集群的单点故障点,每一个集群只有一个NameNode,如果这个机器或进程不可用,整个集群就 ...

  4. Mycat关键特性,什么是MYCAT,MYCAT监控,版本架构,长期规划2.0,Mycat高可用方案

    1.Mycat关键特性 1.1.关键特性 • 支持SQL92标准 • 支持MySQL.Oracle.DB2.SQL Server.PostgreSQL等DB的常见SQL语法 • 遵守Mysql原生协议 ...

  5. 架构成长之路:常见的五种MySQL高可用方案分析

    1. 概述 我们在考虑MySQL数据库的高可用的架构时,主要要考虑如下几方面: 如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中 ...

  6. rocketmq 如何保证高可用_RocketMq容灾、高可用方案

    一.实现分布式集群多副本的三种方式 1.1 M/S模式 即Master/Slaver模式.该模式在过去使用的最多,RocketMq之前也是使用这样的主从模式来实现的.主从模式分为同步模式和异步模式,区 ...

  7. mysql mha好吗_MySQL高可用方案MHA的一些总结和思考

    原标题:MySQL高可用方案MHA的一些总结和思考 MySQL高可用方案中MHA绝地是一个相当成熟的实现.对于数据的切换,其实MGR也能很好的完成,也就是说,数据层面的角色切换已经刻意很平滑的做好了, ...

  8. MySQL集群之五大常见的MySQL高可用方案(转)

    1. 概述 我们在考虑MySQL数据库的高可用的架构时,主要要考虑如下几方面: 如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中 ...

  9. MYSQL(高可用方案)

    本次专题是 MySQL高可用方案选型,这个专题想必有很多同学感兴趣. 高可用的意义以及各种不同高可用等级相应的停机时间我就不必多说了,直接进入主题. 可选MySQL高可用方案 MySQL的各种高可用方 ...

最新文章

  1. android sdk 如何重新生成debug.keystore
  2. 寺库等奢侈品电商补贴下的奢侈品市场,会是怎样的未来
  3. 组装自己的tesla超级计算机
  4. 有两个地方,用到了javabean对象和属性字符串值之间的转换
  5. POJ 2528 Mayor's posters 贴海报 线段树 区间更新
  6. (转载)经典SQL语句大全3-技巧篇
  7. iOS开发-获取rootViewController的正确方式
  8. Unix Windows
  9. oracle退税率后台表,Oracle ERP表信息整理(AP).doc
  10. 计算机网络的abc类地址,abc类私有ip地址范围
  11. 使用cef3开发的浏览器不支持flash问题的解决
  12. 程序员常用的工具网站
  13. 简单10步,建立一个完美的商业网站
  14. 从新东方讲师到AI框架工程师,我的历次职业转折|OneFlow U
  15. xcode结果边栏_XCode属性面板使用说明
  16. Context都没弄明白,还怎么做Android开发?
  17. Linux UART接口调试技巧
  18. 面试官:关于负载均衡你了解多少 | Nginx面试题 | Nginx架构
  19. Python项目--拼图游戏(附源码)
  20. oracle nbu异机恢复,通过NBU进行Oracle异机恢复的实验操作步骤

热门文章

  1. FreeRTOS 任务简介
  2. Linux开发工具3
  3. VR虚拟现实技术类毕业论文文献都有哪些?
  4. 为什么我越来越喜欢画低保真原型?
  5. 3.27下午 口语练习P41
  6. shor 量子算法,合数分解
  7. 史上最强大的procreate笔刷,调色卡,字体分享站点大推荐
  8. 什么叫逐行扫描和隔行扫描
  9. 扫描线(scanning line)是什么?(水平清晰度)(电视行(TVLine))(隔行扫描、逐行扫描)
  10. 使用docker部署nginx搭建简单的idea-2019 jrebel插件激活服务器