zookeeper集群部署
1 环境准备
IP | 主机名 | 部署 | 版本 | OS |
---|---|---|---|---|
11.0.1.131 | zk-01 | JDK11、zookeeper | 3.9.1 | Euler 21.10 LTS |
11.0.1.136 | zk-02 | JDK11、zookeeper | 3.9.1 | Euler 21.10 LTS |
11.0.1.137 | zk-03 | JDK11、zookeeper | 3.9.1 | Euler 21.10 LTS |
2 部署
2.1 JDK11部署
所有zookeeper节点都要部署jdk
1)下载JDK11安装包
https://www.oracle.com/cn/java/technologies/downloads/#java11
注意:必须登录Oracle官网账户才能下载
2)创建JDK目录,个人习惯
[root@zk-01 ~]# cd /home/weihu/
[root@zk-01 weihu]# mkdir jdk
3)上传jdk安装包至指定目录
[root@zk-01 jdk]# ll -tr
总用量 162M
-rw-r--r-- 1 root root 162M 6月 14 20:51 jdk-11.0.23_linux-x64_bin.tar.gz
4)解压
[root@zk-01 jdk]# tar -xf jdk-11.0.23_linux-x64_bin.tar.gz
[root@zk-01 jdk]# ll -tr
总用量 162M
-rw-r--r-- 1 root root 162M 6月 14 20:51 jdk-11.0.23_linux-x64_bin.tar.gz
drwxr-xr-x 9 root root 4.0K 6月 14 20:52 jdk-11.0.23
5)安装jre
jdk11默认不会安装jre,如果要想使程序在tomat等web容器里面正常运行,需要安装jre
# 进入解压目录
[root@zk-01 jdk]# cd jdk-11.0.23
[root@zk-01 jdk-11.0.23]# ll -tr
总用量 36K
-rw-r--r-- 1 10668 10668 1.3K 3月 12 05:17 release
-r--r--r-- 1 10668 10668 160 3月 12 05:17 README.html
drwxr-xr-x 2 root root 4.0K 6月 14 20:52 bin
drwxr-xr-x 4 root root 4.0K 6月 14 20:52 conf
drwxr-xr-x 3 root root 4.0K 6月 14 20:52 include
drwxr-xr-x 2 root root 4.0K 6月 14 20:52 jmods
drwxr-xr-x 72 root root 4.0K 6月 14 20:52 legal
drwxr-xr-x 6 root root 4.0K 6月 14 20:52 lib
drwxr-xr-x 3 root root 4.0K 6月 14 20:52 man
[root@zk-01 jdk-11.0.23]# ./bin/jlink --module-path jmods --add-modules java.desktop --output jre
6)修改环境变量
修改/etc/profile文件,加入jdk相关路径配置
# 编辑/etc/profile,末行加入下面内容
[root@zk-01 jdk-11.0.23]# vim /etc/profile
export JAVA_HOME=/home/weihu/jdk/jdk-11.0.23
export JRE_HOME=${JAVA_HOME}
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
# 加载生效
[root@zk-01 jdk-11.0.23]# source /etc/profile
# 验证(出现以下内容表明jdk安装成功)
[root@zk-01 jdk-11.0.23]# java -version
java version "11.0.23" 2024-04-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.23+7-LTS-222)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.23+7-LTS-222, mixed mode)
2.2 安装zookeeper
1)下载zookeeper安装包
https://archive.apache.org/dist/zookeeper/zookeeper-3.9.1/apache-zookeeper-3.9.1-bin.tar.gz
2)上传安装包至服务器
[root@zk-01 ~]# cd /home/weihu/
[root@zk-01 weihu]# ll -tr
总用量 20M
drwxr-xr-x 3 root root 4.0K 6月 14 21:07 jdk
-rw-r--r-- 1 root root 20M 6月 14 21:12 apache-zookeeper-3.9.1-bin.tar.gz
3)解压安装至 /usr/local 目录下
[root@zk-01 weihu]# tar -xf apache-zookeeper-3.9.1-bin.tar.gz -C /usr/local/
[root@zk-01 weihu]# cd /usr/local/;ll
总用量 44K
drwxr-xr-x 6 root root 4.0K 6月 14 21:14 apache-zookeeper-3.9.1-bin
drwxr-xr-x. 2 root root 4.0K 6月 24 2021 bin
drwxr-xr-x. 2 root root 4.0K 6月 24 2021 etc
drwxr-xr-x. 2 root root 4.0K 6月 24 2021 games
drwxr-xr-x. 2 root root 4.0K 6月 24 2021 include
drwxr-xr-x. 2 root root 4.0K 6月 24 2021 lib
drwxr-xr-x. 3 root root 4.0K 1月 23 18:51 lib64
drwxr-xr-x. 2 root root 4.0K 6月 24 2021 libexec
drwxr-xr-x. 2 root root 4.0K 6月 24 2021 sbin
drwxr-xr-x. 5 root root 4.0K 1月 23 18:51 share
drwxr-xr-x. 2 root root 4.0K 6月 24 2021 src
[root@zk-01 local]#
4)重命名
[root@zk-01 local]# mv apache-zookeeper-3.9.1-bin zookeeper
其余两个节点同样操作(我这里直接将目录拷贝过去了)
[root@zk-01 local]# scp -r zookeeper/ root@11.0.1.136:/usr/local/
[root@zk-01 local]# scp -r zookeeper/ root@11.0.1.137:/usr/local/
5)创建数据目录
[root@zk-01 zookeeper]# mkdir /usr/local/zookeeper/data
[root@zk-02 weihu]# mkdir /usr/local/zookeeper/data
[root@zk-03 weihu]# mkdir /usr/local/zookeeper/data
6)配置文件准备
# 基于模板配置文件生成配置文件
[root@zk-01 ~]# cd /usr/local/zookeeper/conf/
[root@zk-01 conf]# ls
configuration.xsl logback.xml zoo_sample.cfg
[root@zk-01 conf]# cp zoo_sample.cfg zoo.cfg
[root@zk-01 conf]#
[root@zk-01 conf]#
[root@zk-01 conf]# ls
configuration.xsl logback.xml zoo.cfg zoo_sample.cfg
# 修改配置文件
[root@zk-01 conf]# vim /usr/local/zookeeper/conf/zoo.cfg
# 配置文件内容
[root@zk-01 conf]# egrep -v "^#|^$" /usr/local/zookeeper/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper/data
clientPort=2181
maxClientCnxns=128
autopurge.snapRetainCount=3
autopurge.purgeInterval=24
server.1=11.0.1.131:2888:3888
server.2=11.0.1.136:2888:3888
server.3=11.0.1.137:2888:3888
# 配置文件说明
[root@zk-01 conf]# egrep -v "^#|^$" /usr/local/zookeeper/conf/zoo.cfg
tickTime=2000 #服务器与服务器之间的单次心跳检测时间间隔,单位为毫秒
initLimit=10 #集群中leader 服务器与follower服务器初始连接心跳次数,即多少个 2000 毫秒
syncLimit=5 #leader 与follower之间连接完成之后,后期检测发送和应答的心跳次数,如果该follower在设置的时间内(5*2000)不能与leader 进行通信,那么此 follower将被视为不可用。
dataDir=/usr/local/zookeeper/data #自定义的zookeeper保存数据的目录
clientPort=2181 #客户端连接 Zookeeper 服务器的端口,Zookeeper会监听这个端口,接受客户端的访问请求
maxClientCnxns=128 #单个客户端IP 可以和zookeeper保持的连接数
autopurge.snapRetainCount=3 #3.4.0中的新增功能:启用后,ZooKeeper 自动清除功能,会将只保留此最新3个快照和相应的事务日志,并分别保留在dataDir 和dataLogDir中,删除其余部分,默认值为3,最小值为3
autopurge.purgeInterval=24 #3.4.0及之后版本,ZK提供了自动清理日志和快照文件的功能,这个参数指定了清理频率,单位是小时,需要配置一个1或更大的整数,默认是 0,表示不开启自动清理功能
#格式: server.MyID服务器唯一编号=服务器IP:Leader和Follower的数据同步端口(只有leader才会打开):Leader和Follower选举端口(L和F都有)
#如果添加节点,只需要在所有节点上添加新节点的上面形式的配置行,在新节点创建myid文件,并重启所有节点服务即可
server.1=11.0.1.131:2888:3888
server.2=11.0.1.136:2888:3888
server.3=11.0.1.137:2888:3888
7)将配置文件传至其他两节点
[root@zk-01 conf]# scp /usr/local/zookeeper/conf/zoo.cfg root@11.0.1.136:/usr/local/zookeeper/conf/
root@11.0.1.136's password:
zoo.cfg 100% 1302 1.5MB/s 00:00
[root@zk-01 conf]# scp /usr/local/zookeeper/conf/zoo.cfg root@11.0.1.137:/usr/local/zookeeper/conf/
root@11.0.1.137's password:
zoo.cfg 100% 1302 1.6MB/s 00:00
[root@zk-01 conf]#
8)在各个节点上生成myid文件
注意:各个myid文件的内容要和zoo.cfg文件相匹配
[root@zk-01 weihu]# echo 1 > /usr/local/zookeeper/data/myid
[root@zk-02 weihu]# echo 2 > /usr/local/zookeeper/data/myid
[root@zk-03 weihu]# echo 3 > /usr/local/zookeeper/data/myid
9)各节点启动zookeeper服务
# 注意:在所有三个节点快速启动服务,否则会造成集群失败
[root@zk-01 ~]# /usr/local/zookeeper/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@zk-02 ~]# /usr/local/zookeeper/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@zk-03 ~]# /usr/local/zookeeper/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
10)查看状态
[root@zk-01 ~]# hostname -I
11.0.1.131
[root@zk-01 ~]# /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
[root@zk-02 ~]# hostname -I
11.0.1.136
[root@zk-02 ~]# /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
[root@zk-03 ~]# hostname -I
11.0.1.137
[root@zk-03 ~]# /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
# 如果有问题可以查看日志进行排错,我启动的时候发现集群地址都写错了,后查日志发现了
tail -100f /usr/local/zookeeper/logs/zookeeper-root-server-zk-01.out
11)查看端口
只有leader监听2888/tcp端口
[root@zk-01 ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 50 *:2181 *:*
LISTEN 0 50 *:36233 *:*
LISTEN 0 50 [::ffff:11.0.1.131]:3888 *:*
LISTEN 0 50 *:8080 *:*
[root@zk-02 ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 50 [::ffff:11.0.1.136]:3888 *:*
LISTEN 0 50 *:8080 *:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 50 *:36599 *:*
LISTEN 0 50 *:2181 *:*
LISTEN 0 50 [::ffff:11.0.1.136]:2888 *:*
[root@zk-03 ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 50 *:39561 *:*
LISTEN 0 50 [::ffff:11.0.1.137]:3888 *:*
LISTEN 0 50 *:8080 *:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 50 *:2181 *:*
3 访问zookeeper集群
我这里再找一台空机器装zookeeper单节点用于客户端,安装过程略。。。
1)客户端访问(访问哪个节点都可以)
[root@es1 weihu]# zkCli.sh -server 11.0.1.131:2181
.......
SL config status: Will not attempt to authenticate using SASL (unknown error)
2024-06-15 14:05:09,498 [myid:11.0.1.131:2181] - INFO [main-SendThread(11.0.1.131:2181):o.a.z.ClientCnxn$SendThread@996] - Socket connection established, initiating session, client: /11.0.1.133:49138, server: 11.0.1.131/11.0.1.131:2181
2024-06-15 14:05:09,514 [myid:11.0.1.131:2181] - INFO [main-SendThread(11.0.1.131:2181):o.a.z.ClientCnxn$SendThread@1431] - Session establishment complete on server 11.0.1.131/11.0.1.131:2181, session id = 0x100000224aa0001, negotiated timeout = 30000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null zxid: -1
[zk: 11.0.1.131:2181(CONNECTED) 0]
[zk: 11.0.1.131:2181(CONNECTED) 0]
# 输入tab键可以列出所有支持的命令
[zk: 11.0.1.131:2181(CONNECTED) 1]
addWatch addauth close config connect
create delete deleteall delquota get
getAcl getAllChildrenNumber getEphemerals history listquota
ls printwatches quit reconfig redo
removewatches set setAcl setquota stat
sync version whoami
# config命令查看
[zk: 11.0.1.131:2181(CONNECTED) 1] config
server.1=11.0.1.131:2888:3888:participant
server.2=11.0.1.136:2888:3888:participant
server.3=11.0.1.137:2888:3888:participant
version=0
2)创建节点
#默认创建持久节点,即退出不丢失,create -e 可以创建临时节点(退出就丢失)
#持久节点才支持创建子节点,临时节点不支持,如: create /app1/subapp1 “subdata” ,不能递归创建
[zk: 11.0.1.131:2181(CONNECTED) 2] create /test "hello,zookeeper"
Created /test
[zk: 11.0.1.131:2181(CONNECTED) 3]
[zk: 11.0.1.131:2181(CONNECTED) 3] ls /
[test, zookeeper]
[zk: 11.0.1.131:2181(CONNECTED) 4] get /test
hello,zookeeper
[zk: 11.0.1.131:2181(CONNECTED) 5]
# get -s 可以查看更详细的信息
[zk: 11.0.1.131:2181(CONNECTED) 6] get -s /test
hello,zookeeper
cZxid = 0x100000004
ctime = Sat Jun 15 14:09:42 CST 2024
mZxid = 0x100000004
mtime = Sat Jun 15 14:09:42 CST 2024
pZxid = 0x100000004
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 15
numChildren = 0
[zk: 11.0.1.131:2181(CONNECTED) 7]
## 上面是在zk-01节点上创建的数据,现在登录其他节点看看数据是否存在
[root@es1 weihu]# zkCli.sh -server 11.0.1.136:2181
.......
[zk: 11.0.1.136:2181(CONNECTED) 0] ls /
[test, zookeeper]
[zk: 11.0.1.136:2181(CONNECTED) 1] get /test
hello,zookeeper
[zk: 11.0.1.136:2181(CONNECTED) 2]
[root@es1 weihu]# zkCli.sh -server 11.0.1.137:2181
.......
[zk: 11.0.1.137:2181(CONNECTED) 0] ls /
[test, zookeeper]
[zk: 11.0.1.137:2181(CONNECTED) 1] get /test
hello,zookeeper
[zk: 11.0.1.137:2181(CONNECTED) 2]
4 测试zookeeper集群
1)将 leader 节点停止,看看哪个节点会被重新选举为新的 leader 节点
[root@zk-02 ~]# /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
[root@zk-02 ~]# /usr/local/zookeeper/bin/zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
[root@zk-02 ~]#
# 可以在zk-01节点上查看日志,发现11.0.1.137被选为新的leader 节点
[root@zk-01 jdk]# tail -100f /usr/local/zookeeper/logs/zookeeper-root-server-zk-01.out
.........
2024-06-15 14:18:37,065 [myid:] - INFO [LeaderConnector-/11.0.1.137:2888:o.a.z.s.q.Learner$LeaderConnector@380] - Successfully connected to leader, using address: /11.0.1.137:2888
# 验证,在11.0.1.137,也就是zk-03节点上查看zookeeper状态
[root@zk-03 jdk]# /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
[root@zk-03 jdk]#
# 可以看出来确实是zk-03节点被选为新的leader
2)连接节点,继续写入数据,验证集群的可用性
# 连接zk-03节点写入数据
[root@es1 weihu]# zkCli.sh -server 11.0.1.137:2181
......
[zk: 11.0.1.137:2181(CONNECTED) 2] create /test/aaa
Created /test/aaa
[zk: 11.0.1.137:2181(CONNECTED) 7] set /test/aaa ajie
[zk: 11.0.1.137:2181(CONNECTED) 10] ls /test
[aaa]
[zk: 11.0.1.137:2181(CONNECTED) 11] get /test/aaa
ajie
# 连接zk-01节点查看数据
[root@es1 weihu]# zkCli.sh -server 11.0.1.131:2181
[zk: 11.0.1.131:2181(CONNECTED) 0] ls /test
[aaa]
[zk: 11.0.1.131:2181(CONNECTED) 1] get /test/aaa
ajie
[zk: 11.0.1.131:2181(CONNECTED) 2]
# 发现集群仍然可用
3)将zk-02节点启动
会发现会自动成为 follower
[root@zk-02 ~]# /usr/local/zookeeper/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@zk-02 ~]# /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
4)停止两台zookeeper节点,会发生什么呢?
模拟 zk-01 和 zk-02 节点 都出故障
[root@zk-01 jdk]# /usr/local/zookeeper/bin/zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
[root@zk-01 jdk]#
[root@zk-02 ~]# /usr/local/zookeeper/bin/zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
[root@zk-02 ~]#
在zk-03节点上查看zookeepe状态
[root@zk-03 jdk]# /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Error contacting service. It is probably not running.
发现集群已经停止工作了
5 总结
1)集群特性
整个集群中只要有超过集群数量一半的 zookeeper工作是正常的,那么整个集群对外就是可用的假如有 2 台服务器做了一个 Zookeeper 集群,只要有任何一台故障或宕机,那么这个 ZooKeeper集群就不可用了,因为剩下的一台没有超过集群一半的数量,但是假如有三台zookeeper 组成一个集群, 那么损坏一台就还剩两台,大于 3台的一半,所以损坏一台还是可以正常运行的,但是再损坏一台就只剩一台集群就不可用了。那么要是 4 台组成一个zookeeper集群,损坏一台集群肯定是正常的,那么损坏两台就还剩两台,那么2台不大于集群数量的一半,所以 3 台的 zookeeper 集群和 4 台的 zookeeper集群损坏两台的结果都是集群不可用,以此类推 5 台和 6 台以及 7 台和 8台都是同理
2)Zookeeper 事务日志和快照
ZooKeeper集群中的每个服务器节点每次接收到写操作请求时,都会先将这次请求发送给leader,leader将这次写操作转换为带有状态的事务,然后leader会对这次写操作广播出去以便进行协调。当协调通过(大多数节点允许这次写)后,leader通知所有的服务器节点,让它们将这次写操作应用到内存数据库中,并将其记录到事务日志中。
当事务日志记录的次数达到一定数量后(默认10W次),就会将内存数据库序列化一次,使其持久化保存到磁盘上,序列化后的文件称为"快照文件"。每次拍快照都会生成新的事务日志。
3)选举过程
节点角色状态:
LOOKING:寻找 Leader 状态,处于该状态需要进入选举流程
LEADING:领导者状态,处于该状态的节点说明是角色已经是Leader
FOLLOWING:跟随者状态,表示 Leader已经选举出来,当前节点角色是follower
OBSERVER:观察者状态,表明当前节点角色是 observer
选举ID:
ZXID(zookeeper transaction id):每个改变 Zookeeper状态的操作都会自动生成一个对应的zxid。ZXID最大的节点优先选为Leader
myid:服务器的唯一标识(SID),通过配置 myid 文件指定,集群中唯一,当ZXID一样时,myid大的节点优先选为Leader
ZooKeeper 集群选举过程:
(1)当集群中的 zookeeper 节点启动以后,会根据配置文件中指定的 zookeeper节点地址进行leader 选择操作,过程如下:
每个zookeeper 都会发出投票,由于是第一次选举leader,因此每个节点都会把自己当做leader 角色进行选举,每个zookeeper 的投票中都会包含自己的myid和zxid,此时zookeeper 1 的投票为myid 为 1,初始zxid有一个初始值0x0,后期会随着数据更新而自动变化,zookeeper 2 的投票为myid 为2,初始zxid 为初始生成的值。
每个节点接受并检查对方的投票信息,比如投票时间、是否状态为LOOKING状态的投票。
对比投票,优先检查zxid,如果zxid 不一样则 zxid 大的为leader,如果zxid相同则继续对比myid,myid 大的一方为 leader成为 Leader 的必要条件: Leader 要具有最高的zxid;当集群的规模是 n 时,集群中大多数的机器(至少n/2+1)得到响应并从follower 中选出的 Leader。
(2)心跳机制:Leader 与 Follower 利用 PING 来感知对方的是否存活,当 Leader无法响应PING 时,将重新发起 Leader 选举。
当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB(Zookeeper Atomic Broadcast) 协议就会进入恢复模式并选举产生新的Leader服务器。这个过程大致如下:
Leader Election(选举阶段):节点在一开始都处于选举阶段,只要有一个节点得到超半数节点的票数,它就可以当选准 leader。
Discovery(发现阶段):在这个阶段,followers 跟准 leader 进行通信,同步 followers 最近接收的事务提议。
Synchronization(同步阶段):同步阶段主要是利用 leader 前一阶段获得的最新提议历史,同步集群中所有的副本。同步完成之后 准leader 才会成为真正的 leader。
Broadcast(广播阶段) :到了这个阶段,Zookeeper 集群才能正式对外提供事务服务,并且 leader 可以进行消息广播。同时如果有新的节点加入,还需要对新节点进行同步