Zookeeper基础知识

Zookeeper介绍、安装、shell cli使用

Posted by Steven on 2021-04-27
Estimated Reading Time 22 Minutes
Words 5.2k In Total
Viewed Times

一、引入

前面的关于Redis的文章中,关于Redis复制集群数据一致性,说过这么一张图

image-20210427111208362

完成分布式协调很难,因为在解决击穿和穿透都会用到分布式锁,即Redis中的数据没有了,这个时候并发请求获取一些数据,这样就会透传到数据库,有了锁之后,就不会存在并发一下全部压到数据库,其中一层层向后并发流量这个过程很复杂

image-20210427114553709

这就引出了Zookeeper,它可以减轻分布式应用程序从头开始实施协调服务的责任。

二、Zookeeper:分布式协调服务

分布式应用程序的分布式协调服务

ZooKeeper是用于分布式应用程序的分布式,开放源代码协调服务。它公开了一组简单的原语,分布式应用程序可以基于这些原语来实现用于同步,配置维护以及组和命名的更高级别的服务。它的设计易于编程,并使用了按照文件系统熟悉的目录树结构样式设置的数据模型。它以Java运行,并且具有Java和C的绑定。

image-20210427152723614

Zookeeper的数据是保存在内存中的

Zookeeoper是一种复制集群,也就说每个节点上的数据都是一样的

image-20210427153823256

根据这张图,我们大概可以看出:

  1. 整个Zookeeoper是当做一个服务来看的,对外提供服务,可以使用代码实现一些客户端来使用这些服务,

另外,上面的Zookeeoper集群,一谈到集群,肯定就会想到角色,我们看到有其中一个标记为Leader,说明有点像Redis中的主从架构。一说到集群中是主动架构,一定要想到:

  • 一般主负责增删改、从负责读
  • 主从中的主节点是单点的,可能存在的单点故障问题
  1. 客户端想连谁就连谁,而增删改最终是要转到Leader节点上去的

就要带着这些问题思考:

1、Leader可能会挂,那么就会造成 a、服务不可用;b、不可靠的。 —但是事实上,zk集群是极其高可用的(说明有一种方式可以快速的恢复出一个Leader)

2、因此,zk还有可能进入一种状态,就是无主模型 ,即主挂了之后,即会进入无主模型

3、zk从不可用状态恢复到可用状态应该越快越好

因此,zk有两种运行状态:可用状态,不可用状态,他们的区别就是Leader是不是挂掉了

image-20210622154001888

通过文档,可以知道的其他点

1、zk很快,他是读写分离的,并发的数量散在不同的server上,而且整个集群读和写的比例是10:1的话,效果的是好的,就单一个物理机,都可以hold住一秒钟10w读写量

2、虽然名称空间很像文件系统,像个目录树,但是并不是文件和文件夹的概念,而叫做节点,这个节点可以存储数据,但是节点存的数据很少1M(zk旨在存储协调数据:状态信息,配置,位置信息等,不要把它当作数据库用)

3、节点可以分为持久节点和临时节点,另外还有一个序列节点,这个节点不是独立存在的,是依托持久节点或者临时节点的

4、每一个客户端连接到zk的时候,都会产生一个session,来代替这个客户端,

redis是通过锁机制,然后这个锁是有过期时间的,如果设置的时间然后过期了,但是事情没做完,别人就会抢到这把锁,会造成脏数据,而且客户端很麻烦,因为为了解决这个问题需要多线程来解决,所以很麻烦;

而zk引入session概念,只要client在,session也在,如果client挂掉了或者主动断开链接,那么session也随之消失

也就是Redis存在的这块问题:需要加锁,但是锁会有过期时间,需要多线程解决

image-20210428144044227

而zk通过session概念就可以解决这两个问题

image-20210428151458501

Zookeeper可以保证

1、顺序一致性:客户端的更新将按照发送顺序应用

2、原子性:要么成功,要么失败

3、单个系统镜像(统一视图):不论客户连的是哪个服务器,看到的都是相同的服务视图;因为是复制模型,所以不论连接谁,都能看到那个A

4、可靠性/持久性:zk也有持久化,所以数据是可靠的或者说是持久的

5、及时性/实时性:最主要说的是最终一致性的概念,所以说在特定时间范围内数据

三、安装、验证、使用

这里我们准备了四台机器(我的环境是在Mac虚拟化软件中安装了四台虚拟机),最好是在安装好之后,每个给系统做一个干净的快照

image-20210429104725414

并且已经安装好了java环境

1、下载安装

首先下载zookeeper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@node01 /]# cd /soft/
[root@node01 soft]# wget https://mirrors.bfsu.edu.cn/apache/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz
--2021-04-29 11:27:57-- https://mirrors.bfsu.edu.cn/apache/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz
正在解析主机 mirrors.bfsu.edu.cn (mirrors.bfsu.edu.cn)... 39.155.141.16, 2001:da8:20f:4435:4adf:37ff:fe55:2840
正在连接 mirrors.bfsu.edu.cn (mirrors.bfsu.edu.cn)|39.155.141.16|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:12387614 (12M) [application/octet-stream]
正在保存至: “apache-zookeeper-3.7.0-bin.tar.gz”

100%[============================================================================================================================================>] 12,387,614 8.43MB/s 用时 1.4s

2021-04-29 11:27:58 (8.43 MB/s) - 已保存 “apache-zookeeper-3.7.0-bin.tar.gz” [12387614/12387614])

[root@node01 soft]# ll
总用量 153640
-rw-r--r--. 1 root root 12387614 3月 27 18:12 apache-zookeeper-3.7.0-bin.tar.gz
-rw-r--r--. 1 root root 144935989 4月 11 05:47 jdk-8u291-linux-x64.tar.gz?AuthParam=1619666374_b85686b48f4eda0a86a55ac3f627a46b
[root@node01 soft]#

解压

1
2
[root@node01 soft]# mkdir /usr/local/zookeeper
[root@node01 soft]# tar xf apache-zookeeper-3.7.0-bin.tar.gz -C /usr/local/zookeeper/

2、配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@node01 soft]# cd /usr/local/zookeeper/
[root@node01 zookeeper]# cd apache-zookeeper-3.7.0-bin/conf/
[root@node01 conf]# ll
总用量 12
-rw-r--r--. 1 1000 1000 535 3月 17 17:45 configuration.xsl
-rw-r--r--. 1 1000 1000 3435 3月 17 17:45 log4j.properties
-rw-r--r--. 1 1000 1000 1148 3月 17 17:45 zoo_sample.cfg
[root@node01 conf]# cp zoo_sample.cfg zoo.cfg # zk启动默认加载的配置文件是zoo.cfg
[root@node01 conf]# ll
总用量 16
-rw-r--r--. 1 1000 1000 535 3月 17 17:45 configuration.xsl
-rw-r--r--. 1 1000 1000 3435 3月 17 17:45 log4j.properties
-rw-r--r--. 1 root root 1148 4月 29 11:48 zoo.cfg
-rw-r--r--. 1 1000 1000 1148 3月 17 17:45 zoo_sample.cfg
[root@node01 conf]#

编辑zoo.cfg文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# The number of milliseconds of each tick
tickTime=2000 # 服务之间的心跳间隔时间2s
# The number of ticks that the initial
# synchronization phase can take
initLimit=10 # 在follower和Leader建立连接的时候,leader允许等待2s*10=20s的初始延迟
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5 # leader下发同步协作的时候,需要在2*5=10s做出回馈
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/tmp/zookeeper # 持久化目录,最好不要用tem 比如改成/var/zookeeper
# the port at which the clients will connect
clientPort=2181 # 客户端连接zk服务的端口号
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60 # 当前的节点允许的最大客户端连接数
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1 #

## Metrics Providers
#
# https://prometheus.io Metrics Exporter
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
#metricsProvider.httpPort=7000
#metricsProvider.exportJvmInfo=true

由于zk不像redis那样,通过发布订阅就可以知道有哪些节点,所以zk需要人为配置,在上面zoo.cfg文件最后添加

1
2
3
4
server.1=node01:2888:3888 
server.2=node02:2888:3888
server.3=node03:2888:3888
server.4=node04:2888:3888

1、3888端口号是在Leader挂掉之后,或者第一次启动的时候,通过3888建立连接,然后在3888这个端口中进行通信,投票选出Leader,然后leader会启一个2888的端口, 让其他的节点连接2888的端口建立socket连接。后续的,在有leader的情况下,创建节点这些操作都是通过2888 进行通信的

2、server.1、2、3、4是做什么的呢?

这个之前在说LVS的时候说过,在一众多个角色中选出一个leader,这个其实有很多种方式,比如投票最帅的😄,但是有个尴尬的现象就是每个都投自己,那这样一轮下来也选不出来,zk官方也说了200ms就可以选出一个leader,那如何快速的选出呢?

其实不是选出来的,是谦让出来的,每个节点有个数字,数字最大的就是leader,只要启动的节点中之要(个数/2)+1,那么启动的这几台中数字最大的就是leader了

另外,刚才我们把dataDir目录改成了/var/zookeeper,这个就是后面持久化的data目录,这个时候还需要创建一个文件

1
2
[root@node01 conf]# cd /var/zookeeper/
[root@node01 zookeeper]# vi myid

刚才给了在配置的时候server.1=node01:2888:3888 给了1,所以在myid中写一个1即可,保存

3、配置分发

刚才在node01上做了这些配置,那我们要给其他几个节点也要做这些配置,我们直接把当前的配置分发到其他几台机器上:

拷贝到node02

1
2
3
[root@node01 zookeeper]# cd /usr/local/
[root@node01 local]# [root@node01 local]# scp -r ./zookeeper/ root@172.16.197.3:`pwd`
# -r:拷贝 pwd:相同的目录

输入密码即可完成拷贝,但是需要记住,每个节点中/var/zookeeper中的myid是唯一的,需要去相应节点做修改

1
[root@node02 ~]# echo 2 > /var/zookeeper/myid

同理完成node03的分发

1
2
3
4
5
6
7
[root@node01 /]# scp -r /usr/local/zookeeper/  root@172.16.197.2:`pwd`
The authenticity of host '172.16.197.2 (172.16.197.2)' can't be established.
ECDSA key fingerprint is SHA256:BfVLr3MJ33/z7l4LzGpWQaRGc9HTy583df1aRRhNAYg.
ECDSA key fingerprint is MD5:77:03:35:3e:21:a7:04:e3:b5:a0:14:5f:ce:a4:eb:30.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.16.197.2' (ECDSA) to the list of known hosts.
root@172.16.197.2's password:

node03

1
2
3
4
5
[root@node03 ~]# mkdir /var/zookeeper
[root@node03 ~]# echo 3 > /var/zookeeper/myid
[root@node03 ~]# cat /var/zookeeper/myid
3
[root@node03 ~]#

同理做node04的配置

4、配置环境变量

1
[root@node01 /]# vi /etc/profile

添加

1
2
3
export ZOOKEEPER_HOME=/usr/local/zookeeper/apache-zookeeper-3.7.0-bin/

export PATH=${JAVA_HOME}/bin:$PATH:$ZOOKEEPER_HOME/bin
1
[root@node01 /]# source /etc/profile

然后在任何地方输入zk,然后按TAB,就会发现所有指令了。

按照上面说的分发的方法给其他几个节点分发一下/etc/profile

5、启动

我们按照1、2、3、4的顺序启动

1
2
3
4
5
[root@node01 /]# zkServer.sh help
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/apache-zookeeper-3.7.0-bin/bin/../conf/zoo.cfg
Usage: /usr/local/zookeeper/apache-zookeeper-3.7.0-bin//bin/zkServer.sh [--config <conf-dir>] {start|start-foreground|stop|version|restart|status|print-cmd}
[root@node01 /]#

根据help可以看到有这些命令

1
zkServer.sh [--config <conf-dir>] {start|start-foreground|stop|version|restart|status|print-cmd}

启动一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@node01 ~]# zkServer.sh start-foreground
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/apache-zookeeper-3.7.0-bin/bin/../conf/zoo.cfg
2021-04-30 09:58:37,822 [myid:] - INFO [main:QuorumPeerConfig@174] - Reading configuration from: /usr/local/zookeeper/apache-zookeeper-3.7.0-bin/bin/../conf/zoo.cfg
2021-04-30 09:58:37,917 [myid:] - INFO [main:QuorumPeerConfig@444] - clientPortAddress is 0.0.0.0:2181
2021-04-30 09:58:37,917 [myid:] - INFO [main:QuorumPeerConfig@448] - secureClientPort is not set
2021-04-30 09:58:37,917 [myid:] - INFO [main:QuorumPeerConfig@464] - observerMasterPort is not set
2021-04-30 09:58:37,918 [myid:] - INFO [main:QuorumPeerConfig@481] - metricsProvider.className is org.apache.zookeeper.metrics.impl.DefaultMetricsProvider
2021-04-30 09:58:37,961 [myid:] - ERROR [main:QuorumPeerMain@99] - Invalid config, exiting abnormally
org.apache.zookeeper.server.quorum.QuorumPeerConfig$ConfigException: Address unresolved: node01:3888
at org.apache.zookeeper.server.quorum.QuorumPeer$QuorumServer.initializeWithAddressString(QuorumPeer.java:357)
at org.apache.zookeeper.server.quorum.QuorumPeer$QuorumServer.<init>(QuorumPeer.java:278)
at org.apache.zookeeper.server.quorum.QuorumPeer$QuorumServer.<init>(QuorumPeer.java:273)
at org.apache.zookeeper.server.quorum.flexible.QuorumMaj.<init>(QuorumMaj.java:92)
at org.apache.zookeeper.server.quorum.QuorumPeerConfig.createQuorumVerifier(QuorumPeerConfig.java:658)
at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parseDynamicConfig(QuorumPeerConfig.java:689)
at org.apache.zookeeper.server.quorum.QuorumPeerConfig.setupQuorumPeerConfig(QuorumPeerConfig.java:663)
at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parseProperties(QuorumPeerConfig.java:491)
at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parse(QuorumPeerConfig.java:194)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:125)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:91)
Invalid config, exiting abnormally
2021-04-30 09:58:37,983 [myid:] - INFO [main:ZKAuditProvider@42] - ZooKeeper audit is disabled.
2021-04-30 09:58:37,987 [myid:] - ERROR [main:ServiceUtils@42] - Exiting JVM with code 2
[root@node01 ~]#

出错了,看到这句Address unresolved: node01:3888 node01没有解析,看看hosts文件中对node01有没有映射

1
2
3
4
172.16.197.6 node01
172.16.197.3 node02
172.16.197.2 node03
172.16.197.4 node04

我的配置好了,但是还是会出现上面的问题,那就是配置的问题了,自己检查下可能有异常字符之类的,经过排查发现

1
2
3
4
server.1=node01:2888:3888(此处有个空格)
server.2=node02:2888:3888
server.3=node03:2888:3888
server.4=node04:2888:3888

删除了存在的多余的空格,再试试就好了

启动时会提示其他的节点NoRouteToHostException: 没有到主机的路由 (Host unreachable),先不着急,继续启动其他的

启动前记得先关闭防火墙

四台都启动后,新打开客户端,执行zkServer.sh status发现,node04被推选为leader

1
2
3
4
5
6
[root@node04 ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/apache-zookeeper-3.7.0-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
[root@node04 ~]#

我把node04的zk结束,再次查看发现leader很快就变成了node03;重新启动node04,发现leader还是node03,新来的,已经有leader了,只能追随了

6、客户端连接

1
2
3
[root@node04 ~]# zkCli.sh 
.....
[zk: localhost:2181(CONNECTED) 0]

查看客户端相关命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[zk: localhost:2181(CONNECTED) 2] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path [-b batch size]
delquota [-n|-b|-N|-B] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b|-N|-B val path
stat [-w] path
sync path
version
whoami
Command not found: Command not found help
[zk: localhost:2181(CONNECTED) 3]

a、持久节点

创建create,就会多出来一个节点

1
2
3
4
5
[zk: localhost:2181(CONNECTED) 3] create /ooxx ""
Created /ooxx
[zk: localhost:2181(CONNECTED) 4] ls /
[ooxx, zookeeper]
[zk: localhost:2181(CONNECTED) 5]

getset

1
2
3
4
5
6
7
[zk: localhost:2181(CONNECTED) 6] get /ooxx

[zk: localhost:2181(CONNECTED) 7] set /ooxx "hello"
[zk: localhost:2181(CONNECTED) 8] get /ooxx
hello
[zk: localhost:2181(CONNECTED) 9]

每个数据节点都会有cZxid,因为zk是顺序执行,顺序执行就是体现在这个Id上,所有的写操作,都会交给leader来处理,尔leader是单节点,单机维护一个单调递增的计数器很容易;

mZxid修改后的Id

pZxid是与 该节点的子节点(或该节点)的最近一次 创建 / 删除 的时间戳对应

cZxid

对应为该节点的创建时间(Create)

mZxid

对应该节点的最近一次修改的时间(Mofify)

与其子节点无关

pZxid

这个节点就和子节点有关啦!

是与该节点的子节点(或该节点)的最近一次 创建 / 删除 的时间戳对应

注:只与本节点/该节点的子节点,有关;与孙子节点无关。

b、临时节点

set -e /xxoo 创建临时节点,伴随着session的,客户端退出,节点就会消失;而上面说的情况都是持久节点

开启一个客户端,连接了某一台server,创建一个临时节点,如果这个时候这个server节点挂了,zk会连接到另外一个节点(重新建立socket连接),那这个临时节点数据会不会消失?

1、答案是不会消失,其实session也会统一视图,也就是说客户端连接成功后,不止连接的server有这个session,其他的server也有这个session1、

2、所以说所有的server上的任何一次事务操作就会有一个唯一的自增的id,比如开启一个新的客户端,也会消耗一个事务id,直观的体现就是因为开启新的客户端需要做数据同步,所以当再任何客户端在吃执行写操作,就会发现cZxid跳了一个id,比如,开启客户端之前,写操作的cZxid是12,开启之后,再次写操作cZxid变成了14

3、综上,session也是需要消耗cZxid的

c、序列节点

如果我想在/aaa节点下创建数据,有很多的客户端都想在/aaa下创建节点来存储数据,这种在分布式的情况下,大家对这一个地方写东西的情况,有可能会出现一个现象:

数据会覆盖 ,如何解决,这就是序列节点

1
create -s /aaa/xxx
1
2
3
4
5
6
[zk: localhost:2181(CONNECTED) 10] create /aaa ""
Created /aaa
[zk: localhost:2181(CONNECTED) 11] create -s /aaa/xxx "sdadas"
Created /aaa/xxx0000000000
[zk: localhost:2181(CONNECTED) 12]

只要带了-s,就不会覆盖创建,而是会在节点后面拼接一些东西,大家会拿到会是不会重复的节点名称,可以叫做分布式Id

当我们把这个节点删除后,再新建一个,那么这个分布式Id就会是xxx0000000001,而不是xxx0000000000,这个zk内部会做维护

7、作用

有了上面的知识,我们就能想到zk的一些作用了

1、统一配置管理(基于所有的分布式节点只要记住一个path,记住一个ID,就可以找到节点中1M的数据),任何的客户端连接任何的sever都可以拿这个配置

2、分组管理(基于path结构(命名空格键))

3、统一命名(基于序列(-s(sequential))能力)

4、分布式同步(基于临时节点能力)

应用场景

1、分布式锁-上面的第四点的应用场景就是分布式锁【需要客户端代码实现】

设计一个临时节点,我在锁就在,我挂锁就没,别人就可以拿到这把锁

如果依托一个父节点,且具备-s,代表父节点下可以有多把锁(队列式锁,事务的锁)

2、高可用,选主

image-20210623135507538

8、实战

在node01上,我们看一下

1
2
3
4
5
6
7
[root@node01 ~]netstat -natp | egrep '(2888|3888)'
tcp6 0 0 172.16.197.6:3888 :::* LISTEN 2296/java
tcp6 0 0 172.16.197.6:3888 172.16.197.2:55854 ESTABLISHED 2296/java
tcp6 0 0 172.16.197.6:3888 172.16.197.4:46846 ESTABLISHED 2296/java
tcp6 0 0 172.16.197.6:52702 172.16.197.2:2888 ESTABLISHED 2296/java
tcp6 0 0 172.16.197.6:3888 172.16.197.3:34402 ESTABLISHED 2296/java
[root@node01 ~]#

可以看到node01节点上关于28883888所有的连接信息

node01是整个配置文件中的第一个条目,且id号是最小的;

node01开启了一个3888的端口监听

他自己的3888端口被其他三个节点连接了,且自己还拿了一个随机的端口连接了leader的2888端口


再看node02

1
2
3
4
5
6
7
8
[root@node02 ~]# netstat -natp | egrep '(2888|3888)'
tcp6 0 0 172.16.197.3:3888 :::* LISTEN 2247/java
tcp6 0 0 172.16.197.3:55030 172.16.197.2:2888 ESTABLISHED 2247/java
tcp6 0 0 172.16.197.3:3888 172.16.197.2:47380 ESTABLISHED 2247/java
tcp6 0 0 172.16.197.3:3888 172.16.197.4:43374 ESTABLISHED 2247/java
tcp6 0 0 172.16.197.3:34402 172.16.197.6:3888 ESTABLISHED 2247/java
[root@node02 ~]#

image-20210508144539627

通过zkServer.sh status我们发现,,node03是Leader,查看node03

1
2
3
4
5
6
7
8
9
[root@node03 ~]# netstat -natp | egrep '(2888|3888)'
tcp6 0 0 172.16.197.2:3888 :::* LISTEN 4438/java
tcp6 0 0 172.16.197.2:2888 :::* LISTEN 4438/java
tcp6 0 0 172.16.197.2:3888 172.16.197.4:47340 ESTABLISHED 4438/java
tcp6 20 0 172.16.197.2:2888 172.16.197.4:35302 ESTABLISHED 4438/java
tcp6 0 0 172.16.197.2:2888 172.16.197.3:59198 ESTABLISHED 4438/java
tcp6 0 0 172.16.197.2:54088 172.16.197.6:3888 ESTABLISHED 4438/java
tcp6 0 0 172.16.197.2:57278 172.16.197.3:3888 ESTABLISHED 4438/java
tcp6 20 0 172.16.197.2:2888 172.16.197.6:45850 ESTABLISHED 4438/java

3888: 选主投票用的

4888:leader接受write请求用的

没必要每个节点都需要跟其他节点连接一次(不需要每个节点都开启3888跟其他节点连一次),只需要开启一个链接,即可开启双向通信

这块东西在下一篇文章中要用到~


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !