一. Zookeeper简介
1.1 什么是Zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,Google的Chubby一个开源的实现,是大数据生态中的重要组件。它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
它是一个为分布式应用提供一致性协调服务的中间件
1.2 ZooKeeper提供了什么
文件系统
Zookeeper提供一个多层级的节点命名空间(节点称为znode)。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。Zookeeper为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得Zookeeper不能用于存放大量的数据,每个节点的存放数据上限为1M。
通知机制
client端会对某个znode建立一个watcher事件,当该znode发生变化时,这些client会收到zk的通知,然后client可以根据znode变化来做出业务上的改变等。
1.3 Zookeeper作用
master节点选举, 主节点down掉后, 从节点就会接手工作, 并且保证这个节点是唯一的,这也就是所谓首脑模式,从而保证我们集群是高可用的统一配置文件管理, 即只需要部署一台服务器, 则可以把相同的配置文件同步更新到其他所有服务器, 此操作在云计算中用的特别多(例如修改了redis统一配置)
数据发布与订阅, 类似消息队列MQ分布式锁,分布式环境中不同进程之间争夺资源,类似于多进程中的锁集群管理, 保证集群中数据的强一致性
1.4 Zookeeper的特性
一致性: 数据一致性, 数据按照顺序分批入库
原子性: 事务要么成功要么失败
单一视图: 客户端连接集群中的任意zk节点, 数据都是一致的
可靠性:每次对zk的操作状态都会保存在服务端
实时性: 客户端可以读取到zk服务端的最新数据
软件包ZooKeeper
提取码:6ugy
一.单机安装Zookeeper
#上传JDK包
#安装JDK环境
[root@zookeeper ~]# tar zxf jdk-8u211-linux-x64.tar.gz -C /usr/local/
[root@zookeeper ~]# vim /etc/profile # 编辑Java变量
..........................
export JAVA_HOME=/usr/local/jdk1.8.0_211
export JRE_HOME=/usr/local/jdk1.8.0_211/jre
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
[root@zookeeper ~]# source /etc/profile # 执行使配置生效
[root@zookeeper ~]# java -version # 查看是否安装成功
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
#上传zookeeper包
#安装zookeeper
[root@zookeeper ~]# tar zxf zookeeper-3.4.14.tar.gz -C /usr/local/
[root@zookeeper ~]# vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.14
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$ZOOKEEPER_HOME/bin:$PATH # 加入Java配置的PATH中
[root@zookeeper ~]# source /etc/profile
[root@zookeeper ~]# cd /usr/local/zookeeper-3.4.14/conf/
[root@zookeeper conf]# cp zoo_sample.cfg zoo.cfg
[root@zookeeper conf]# mkdir -p /usr/local/zookeeper-3.4.14/data # 创建数据目录
[root@zookeeper conf]# sed -i "s/dataDir=\/tmp\/zookeeper/dataDir=\/usr\/local\/zookeeper-3.4.14\/data/g" zoo.cfg
[root@zookeeper conf]# zkServer.sh start # 启动服务
[root@zookeeper conf]# netstat -anput | grep 2181 # 确定端口在监听
tcp6 0 0 :::2181 :::* LISTEN 4903/java
客户端命令操作
[root@zookeeper ~]# zkCli.sh # 后面不加任何参数默认连接localhost本机的2181端口
Connecting to localhost:2181
[zk: localhost:2181(CONNECTED) 0] help # 显示客户端支持的命令
[zk: localhost:2181(CONNECTED) 1] ls / # 查看当前zk中所包含的内容
[zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls2 / # 查看当前zk中的内容及详情
[zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: localhost:2181(CONNECTED) 3] create /test1 neirong # 创建一个节点
Created /test1
[zk: localhost:2181(CONNECTED) 4] ls / # 可以看到已经多了一个test1
[zookeeper, test1]
[zk: localhost:2181(CONNECTED) 5] get /test1 # huo获取节点信息,需写绝对路径
neirong # 节点数据信息
cZxid = 0x2 # 节点创建时额zxid
ctime = Sat Apr 04 16:15:30 CST 2020 # 节点创建的时间
mZxid = 0x2
mtime = Sat Apr 04 16:15:30 CST 2020 # 节点最近一次更新的时间
pZxid = 0x2
cversion = 0 # 子结点数据更新次数
dataVersion = 0 # 本节点数据更新次数
aclVersion = 0 # 节点ACL的更新次数
ephemeralOwner = 0x0
dataLength = 7 # 节点数据长度
numChildren = 0 # 子结点的数量
[zk: localhost:2181(CONNECTED) 6] set /test1 "gengxin" # 更新节点数据
[zk: localhost:2181(CONNECTED) 7] get /test1 # 可以看到已经更改为新的数据
gengxin
[zk: localhost:2181(CONNECTED) 8] history # 列出zui最近所使用的命令
0 - help
1 - ls /
2 - ls2 /
3 - create /test1 neirong
4 - ls /
5 - get /test1
6 - set /test1 "gengxin"
7 - get /test1
8 - history
[zk: localhost:2181(CONNECTED) 9] delete /test1 # 删除节点,但是无法删除拥有子节点的 节点
[zk: localhost:2181(CONNECTED) 11] rmr /test1 # rmrk可以删除带有子节点的节点
二.zookeeper单机伪集群部署
在一台主机上跑多个zk实例,每个zk实例对应一个独立的配置文件;但是每个配置文件的clientPort & dataDir & dataLogDir绝对不能相同,还需要在dataDir中创建myid文件来指定该dataDir对应的zk实例。
环境如下:
这里在一台物理服务器上,部署3个zk实例
1.安装JDK
#上传JDK包
#安装JDK环境
[root@zookeeper ~]# tar zxf jdk-8u211-linux-x64.tar.gz -C /usr/local/
[root@zookeeper ~]# vim /etc/profile # 编辑Java变量
..........................
export JAVA_HOME=/usr/local/jdk1.8.0_211
export JRE_HOME=/usr/local/jdk1.8.0_211/jre
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
[root@zookeeper ~]# source /etc/profile # 执行使配置生效
[root@zookeeper ~]# java -version # 查看是否安装成功
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
2.安装zookeeper
#上传zookeeper包
[root@zookeeper ~]# tar zxf zookeeper-3.4.14.tar.gz -C /usr/local/
[root@zookeeper ~]# vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.14
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$ZOOKEEPER_HOME/bin:$PATH
[root@zookeeper ~]# source /etc/profile
#创建数据目录
[root@zookeeper ~]# mkdir -p /usr/local/zookeeper-3.4.14/{data_0,data_1,data_2}
#创建myid文件,并填入ID值
[root@zookeeper ~]# echo 0 > /usr/local/zookeeper-3.4.14/data_0/myid
[root@zookeeper ~]# echo 1 > /usr/local/zookeeper-3.4.14/data_1/myid
[root@zookeeper ~]# echo 2 > /usr/local/zookeeper-3.4.14/data_2/myid
#创建事务日志目录,官方建立尽量给事务日志作单独的磁盘或挂载点,这会极大的提高zk性能
[root@zookeeper ~]# mkdir -p /usr/local/zookeeper-3.4.14/{logs_0,logs_1,logs_2}
#配置server0
[root@zookeeper ~]# cd /usr/local/zookeeper-3.4.14/conf/
[root@zookeeper conf]# cp zoo_sample.cfg zoo_0.cfg
[root@zookeeper conf]# egrep -v "^$|^#" zoo_0.cfg # 修改配置文件为如下
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper-3.4.14/data_0/
clientPort=2180
dataLogDir=/usr/local/zookeeper-3.4.14/logs_0/
server.0=127.0.0.1:2287:3387
server.1=127.0.0.1:2288:3388
server.2=127.0.0.1:2289:3389
#配置server1
[root@zookeeper conf]# cp zoo_0.cfg zoo_1.cfg # 复制之前的配置文件,修改个别参数
[root@zookeeper conf]# vim zoo_1.cfg
dataDir=/usr/local/zookeeper-3.4.14/data_1/
clientPort=2181
dataLogDir=/usr/local/zookeeper-3.4.14/logs_1/
#配置server2
[root@zookeeper conf]# cp zoo_0.cfg zoo_2.cfg
[root@zookeeper conf]# vim zoo_2.cfg
dataDir=/usr/local/zookeeper-3.4.14/data_2/
clientPort=2182
dataLogDir=/usr/local/zookeeper-3.4.14/logs_2/
[root@zookeeper conf]# zkServer.sh start zoo_0.cfg # 我这里是在conf目录下,所以后面直接接着配置文件,如果不在conf下,则需写全路径
#启动各实例
[root@zookeeper conf]# zkServer.sh start zoo_1.cfg
[root@zookeeper conf]# zkServer.sh start zoo_2.cfg
[root@zookeeper conf]# netstat -anput | grep java
tcp6 0 0 :::2180 :::* LISTEN 9251/java
tcp6 0 0 :::2181 :::* LISTEN 9291/java
tcp6 0 0 :::2182 :::* LISTEN 9334/java
#列出JVM
[root@zookeeper conf]# jps
9377 Jps
9251 QuorumPeerMain
9334 QuorumPeerMain
9291 QuorumPeerMain
#各实例都启动之后就可以使用客户端进行连接了
[root@zookeeper conf]# zkCli.sh -server 127.0.0.1:2180 # 例
关于多个server的配置说明: 这些server表单服务器的条目。列出组成ZooKeeper服务的服务器。当服务器启动 时,它通过在数据目录中查找文件myid来知道它是哪个服务器。该文件包含服务器号。 最后,注意每个服务器 名后面的两个端口号:“2287”和“3387”。对等点使用前一个端口连接到其他对等点。这样的连接是必要的,以便 对等点可以通信,例如,就更新的顺序达成一致。更具体地说,ZooKeeper服务器使用这个端口将追随者连接 到leader。当一个新的领导者出现时,追随者使用这个端口打开一个TCP连接到领导者。由于默认的领导人选举 也使用TCP,我们目前需要另一个端口的领导人选举。这是服务器条目中的第二个端口。
三.ZooKeeper多机集群部署
三台服务器上都需要执行如下操作
#安装好JDK
[root@zookeeper01 ~]# java -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
#安装好zookeeper
[root@zookeeper01 ~]# tar zxf zookeeper-3.4.14.tar.gz -C /usr/local/
[root@zookeeper01 ~]# vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.14
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$ZOOKEEPER_HOME/bin:$PATH # 加入Java配置的PATH中
[root@zookeeper01 ~]# source /etc/profile
server0配置
[root@zookeeper01 ~]# mkdir -p /usr/local/zookeeper-3.4.14/{data,logs}
[root@zookeeper01 ~]# echo 0 > /usr/local/zookeeper-3.4.14/data/myid
[root@zookeeper01 ~]# cd /usr/local/zookeeper-3.4.14/conf/
[root@zookeeper01 conf]# cp zoo_sample.cfg zoo.cfg
[root@zookeeper01 conf]# egrep -v "^$|^#" zoo.cfg # 修改配置文件为如下
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper-3.4.14/data/
clientPort=2181
dataLogDir=/usr/local/zookeeper-3.4.14/logs
server.0=192.168.1.14:2288:3388
server.1=192.168.1.15:2288:3388
server.2=192.168.1.16:2288:3388
[root@zookeeper01 conf]# zkServer.sh start # 启动实例
[root@zookeeper01 conf]# netstat -anput | grep java # 确定端口在监听
tcp6 0 0 :::43542 :::* LISTEN 40355/java
tcp6 0 0 192.168.1.14:3388 :::* LISTEN 40355/java
tcp6 0 0 :::2181 :::* LISTEN 40355/java
server1配置
[root@zookeeper02 ~]# mkdir -p /usr/local/zookeeper-3.4.14/{data,logs}
[root@zookeeper02 ~]# echo 1 > /usr/local/zookeeper-3.4.14/data/myid
[root@zookeeper02 ~]# cd /usr/local/zookeeper-3.4.14/conf/
[root@zookeeper02 conf]# scp root@192.168.1.14:/usr/local/zookeeper-3.4.14/conf/zoo.cfg ./
[root@zookeeper02 conf]# zkServer.sh start
[root@zookeeper02 conf]# netstat -anput | grep java
tcp6 0 0 192.168.1.15:3388 :::* LISTEN 40608/java
tcp6 0 0 :::2181 :::* LISTEN 40608/java
server2配置
[root@zookeeper03 ~]# mkdir -p /usr/local/zookeeper-3.4.14/{data,logs}
[root@zookeeper03 ~]# echo 2 > /usr/local/zookeeper-3.4.14/data/myid
[root@zookeeper03 ~]# cd /usr/local/zookeeper-3.4.14/conf/
[root@zookeeper03 conf]# scp root@192.168.1.14:/usr/local/zookeeper-3.4.14/conf/zoo.cfg ./
[root@zookeeper03 conf]# zkServer.sh start
[root@zookeeper03 conf]# netstat -anput | grep java
tcp6 0 0 192.168.1.16:3388 :::* LISTEN 12769/java
tcp6 0 0 :::2181 :::* LISTEN 12769/java
查看各zk节点的状态
[root@zookeeper01 /]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: follower
[root@zookeeper02 /]# zkServer.sh status # 02服务器为leader
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: leader
[root@zookeeper03 /]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: follower