# 目录
[TOC]
# 一、Linux 下手动安装 Zookeeper
## 单机模式
1、下载安装
注意:需要先安装Java环境
点击 [http://archive.apache.org/dist/zookeeper/](http://archive.apache.org/dist/zookeeper/) ,进入到要下载的版本,选择 `.tar.gz` 文件下载
下载完成后,使用 `tar` 命令进行解压
```shell
tar -zxvf zookeeper-3.4.14.tar.gz -C /opt
```
进入到 `opt` 目录下,创建 `data` 和 `logs` 目录用于储存数据和日志
```shell
cd /opt
mv zookeeper-3.4.14 zk
cd zk
mkdir data && mkdir logs
```
2、配置
在 `conf` 目录下新建 `zoo.cfg` 文件,写入以下内容保存
```shell
tickTime=2000
dataDir=/opt/zk/data
dataLogDir=/opt/zk/data
clientPort=2181
```
启动测试,进入 `bin` 目录,启动zk
```
zkServer.sh start
```
查看启动状态,检查是否启动成功
```
./zkServer.sh status
```

停止、重启
```
./zkServer.sh stop
./zkServer.sh restart
```
启动之后我,使用 `zkCli.sh` 连接到zk测试
```
./zkCli.sh -server 127.0.0.1:2181
```
连接成功

## 集群模式
集群模式就是多个 zookeeper 组成一个集群,相互通讯,并选举出一个节点 `leader`(主节点)其他节点则作为 `folower` (从节点)。
这里我们在 3台 Linux上进行部署,IP分别为:
- 192.168.1.1(节点1)
- 192.168.1.2(节点2)
- 192.168.1.3(节点3)
参考 “单机模式” 的下载、安装流程,在配置部分我们做出一些改动,修改 `zoo.cfg` 文件如下内容
```
tickTime=2000
dataDir=/opt/zk/data
dataLogDir=/opt/zk/logs
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.1.1:2888:3888
server.2=192.168.1.2:2888:3888
server.3=192.168.1.3:2888:3888
```
在三个节点上分别写入一个 `myid` 文件,内容为节点的编号 1、2、3 等
```shell
# 节点1
echo 1 > data/myid
# 节点2
echo 2 > data/myid
# 节点3
echo 3 > data/myid
```
> 这里的 myid 文件每台节点上都必须要有,根据各自的编号创建即可,否则会启动失败
分别在三个节点上都启动 zookeeper
```
./zkServer.sh start
```
> 这里要注意的是,需要所有节点都启动了才能看到正常的启动状态,否则查看启动状态时将会出现:
>
> “Error contacting service. It is probably not running.”
>
> 但实际本地的zk进程已经启动
所有节点都启动成功后,我们来看一下所有节点的启动和集群选举的状态

连接到zk进行测试
```shell
./zkCli.sh -server 192.168.1.35:2181
```
测试
```shell
[zk: 192.168.1.35:2181(CONNECTED) 0]
[zk: 192.168.1.35:2181(CONNECTED) 0] create /test "hello zk"
Created /test
[zk: 192.168.1.35:2181(CONNECTED) 1]
[zk: 192.168.1.35:2181(CONNECTED) 1] get /test
hello zk
cZxid = 0x100000002
ctime = Tue Nov 24 15:33:43 CST 2020
mZxid = 0x100000002
mtime = Tue Nov 24 15:33:43 CST 2020
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
[zk: 192.168.1.35:2181(CONNECTED) 2] delete /test
[zk: 192.168.1.35:2181(CONNECTED) 3] get /test
Node does not exist: /test
[zk: 192.168.1.35:2181(CONNECTED) 4]
[zk: 192.168.1.35:2181(CONNECTED) 4]
[zk: 192.168.1.35:2181(CONNECTED) 4] exit
```
# 二、基于 Docker 安装 Zookeeper
> Zookeeper 部署有三种方式,单机模式、集群模式、伪集群模式,以下采用 Docker 的方式部署
>
> **注意:** 集群为大于等于3个奇数,如 3、5、7,不宜太多,集群机器多了选举和数据同步耗时长,不稳定。
## 单机模式
先安装 `docker-compose` ,安装步骤参考 [Docker Compose | 菜鸟教程 (runoob.com)](https://www.runoob.com/docker/docker-compose.html)
编写 `docker-compose.yml`
```
version: '3.1'
services:
zoo1:
image: zookeeper
restart: always
hostname: zoo1
ports:
- 2181:2181
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=zoo1:2888:3888
```
执行 `docker-compose up -d` ,等待容器启动
以交互的方式进入容器
```
docker exec -it zookeeper_zoo1_1 /bin/bash
```
使用客户端连接到服务端
```
bash-4.3# ./bin/zkCli.sh -server 192.168.75.130:2181
Connecting to 192.168.75.130:2181
2017-11-09 07:45:58,365 [myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.10-39d3a4f269333c922ed3db283be479f9deacaa0f, built on 03/23/2017 10:13 GMT
2017-11-09 07:45:58,374 [myid:] - INFO [main:Environment@100] - Client environment:host.name=zoo1
```
使用服务端工具检查服务器状态
```
bash-4.3# ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Mode: standalone
```
## 集群模式
准备 3 台 Linux 系统,并分别配置 Zookeeper,系统的IP如下
1. 192.168.1.1
2. 192.168.1.2
3. 192.168.1.3
**1、第一台主机**
配置 docker-compose.yml
```
version: '3.1'
services:
zoo1:
image: zookeeper
restart: always
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=192.168.1.1:2888:3888 server.2=192.168.1.2:2888:3888 server.3=192.168.1.3:2888:3888
network_mode: host
```
> ZOO_SERVERS 为集群节点的IP
启动,并验证测试
```text
root@UbuntuBase:/usr/local/docker/zookeeper# docker exec -it zookeeper_zoo1_1 /bin/bash
bash-4.3# ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Mode: leader
```
**2、第二台主机**
配置 docker-compose.yml
```
version: '3.1'
services:
zoo2:
image: zookeeper
restart: always
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=192.168.75.130:2888:3888 server.2=192.168.75.134:2888:3888 server.3=192.168.75.135:2888:3888
network_mode: host
```
启动,并验证测试
```
root@UbuntuBase:/usr/local/docker/zookeeper# docker exec -it zookeeper_zoo2_1 /bin/bash
bash-4.3# ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Mode: follower
```
**3、第三台主机**
配置 docker-compose.yml
```
version: '3.1'
services:
zoo3:
image: zookeeper
restart: always
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=192.168.75.130:2888:3888 server.2=192.168.75.134:2888:3888 server.3=192.168.75.135:2888:3888
network_mode: host
```
启动,并验证测试
```
root@UbuntuBase:/usr/local/docker/zookeeper# docker exec -it zookeeper_zoo3_1 /bin/bash
bash-4.3# ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Mode: follower
```
## 伪集群模式
单台机器运行多个容器实现集群,这样仍然会有单机容错的问题,所以只适合测试环境
1、编写 `docker-compose.yml`
```yml
version: '3.1'
services:
zoo1:
image: zookeeper
restart: always
hostname: zoo1
ports:
- 2181:2181
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
zoo2:
image: zookeeper
restart: always
hostname: zoo2
ports:
- 2182:2181
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
zoo3:
image: zookeeper
restart: always
hostname: zoo3
ports:
- 2183:2181
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
```
> 容器内通过 hostname 代替 IP地址来进行通讯,例如 zoo1、zoo2、zoo3
2、启动容器
```
docker-compose up -d
```
3、验证是否安装成功
分别以交互方式进入容器查看
```text
docker exec -it zookeeper_zoo1_1 /bin/bash
```
```text
docker exec -it zookeeper_zoo2_1 /bin/bash
```
```text
docker exec -it zookeeper_zoo3_1 /bin/bash
```
4、使用服务端工具检查服务器状态
```text
root@UbuntuBase:/usr/local/docker/zookeeper# docker exec -it zookeeper_zoo1_1 /bin/bash
bash-4.3# ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Mode: follower
```
```text
root@UbuntuBase:/usr/local/docker/zookeeper# docker exec -it zookeeper_zoo2_1 /bin/bash
bash-4.3# ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Mode: follower
```
```text
root@UbuntuBase:/usr/local/docker/zookeeper# docker exec -it zookeeper_zoo3_1 /bin/bash
bash-4.3# ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Mode: leader
```
# 三、Zookeeper配置说明
## 工作模式与端口号
Zookeeper 的三种工作模式
- 单机模式:存在单点故障
- 集群模式:在多台机器上部署 Zookeeper 集群,适合线上环境上使用。
- 伪集群模式:在同一台机器上运行多个实例,集群配置中的端口需要错开,仍然有单点故障的问题,适合实验环境模拟集群来使用。
Zookeeper 常见的三个端口号:
- 2181:客户端连接 Zookeeper 集群使用的监听端口号
- 3888:选举 leader 使用
- 2888:集群内机器通讯使用(Leader 和 Follower 之间数据同步使用的端口号,Leader 监听此端口)
## Zookeeper 单机模式配置文件
配置文件路径:`/conf/zoo.cfg`
```s
clientPort=2181
dataDir=/data
dataLogDir=/datalog
tickTime=2000
```
- clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
- dataDir:Zookeeper 保存数据的目录。
- dataLogDir:Zookeeper 保存日志的目录。
- tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每隔 tickTime 时间就会发送一个心跳。
## Zookeeper 集群模式配置文件
配置文件路径:`/conf/zoo.cfg`
```
clientPort=2181
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
server.1=192.168.0.1:2888:3888
server.2=192.168.0.2:2888:3888
server.3=192.168.0.3:2888:3888
```
- initLimit:
配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。
当已经超过 initLimit(默认为 10) 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5 * 2000 = 10 秒
- syncLimit:
配置 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2 * 2000 = 4 秒
- 定时清理(Zookeeper 从 3.4.0 开始提供了自动清理快照和事务日志的功能)以下两个参数配合使用:
- autopurge.purgeInterval:
指定了清理频率,单位是小时,需要填写一个 1 或更大的整数,默认是 0,表示不开启自己清理功能。
- autopurge.snapRetainCount:
指定了需要保留的文件数目。默认是保留 3 个。
- maxClientCnxns:
限制连接到 Zookeeper 的客户端的数量,限制并发连接的数量,它通过 IP 来区分不同的客户端。此配置选项可以用来阻止某些类别的 Dos 攻击。将它设置为 0 或者忽略而不进行设置将会取消对并发连接的限制。
- server.A=B:C:D:
其中 A 是一个数字,表示这个是第几号服务器。B 是这个服务器的 IP 地址。C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口(2888);D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口(3888)。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
**注意:** `server.A` 中的 A 是在 `dataDir` 配置的目录中创建一个名为 `myid` 的文件里的值(如:1)
Zookeeper安装与部署