文章目录
  1. 1.概述
    1. 1.1 ZAB协议
      1. 1.1.1 领导选举(Leader Election)
      2. 1.1.2 信息同步(Atomic broadcast)
    2. 1.2 内部原理
    3. 1.3 系统要求
  2. 2.Linux 下安装
    1. 2.1 下载并解压(35M)
    2. 2.2 设置环境变量
    3. 2.3 准备目录与配置文件
    4. 2.4 服务的配置并启动
    5. 2.5 防火墙放行
    6. 2.6 客户端验证
    7. 2.7 清空数据【慎用】
    8. 2.8 卸载服务【慎用】
  3. 3.Windows 下安装(可用于开发)
    1. 3.1 下载
    2. 3.2 安装
      1. 3.2.1 解压
      2. 3.2.2 修改系统环境变量
      3. 3.2.3 修改 conf\zoo-%n.cfg
      4. 3.2.4 修改脚本
    3. 3.3 启动服务
    4. 3.4 客户端验证
  4. 4.集群部署(生产环境)

ZooKeeper 是大型分布式系统中可靠的协调系统,它以树状结构存储数据,以领导选举和信息同步机制保证了集群的高可用性,以事件通知机制协助事件订阅者及时捕获数据的变化,可协助实现 Dubbo、Kafka 等架构。本文以 CentOS 和 Windows 为例,总结了 ZooKeeper 集群的部署操作,并以自带的脚本命令操作其数据。

作者:王克锋
出处:https://kefeng.wang/2017/11/08/zookeeper-deploy/
版权:自由转载-非商用-非衍生-保持署名,转载请标明作者和出处。

1.概述

ZooKeeper 是 Hadoop 的一个子项目,是大型分布式系统中可靠的协调系统。分布式应用程序以此实现更高级别的服务,可用于分布式系统的配置维护、名字服务、分布式同步、组服务等:

  • 用于 Dubbo: 作为配置中心;
  • 用于 Kafka: 作为 Broker/Producer/Consumer 共享的配置中心。

官网首页: https://zookeeper.apache.org/
官网文档: https://zookeeper.apache.org/doc/current/

1.1 ZAB协议


集群间通过 ZAB(ZooKeeper Atomic Broadcast)协议保持数据一致性,该协议包括两个阶段:

1.1.1 领导选举(Leader Election)

  • 选举出一个 Leader(所有写操作传送给 Leader),其他机器被称为 Follower;
  • 当前 Leader 崩溃或失去大多数 Follower 后,会选举出新的 Leader;

1.1.2 信息同步(Atomic broadcast)

用于同步 Leader 与 Follower 之间的信息,保证数据一致。

1.2 内部原理

https://zookeeper.apache.org/doc/current/zookeeperOver.html
存储方式与标准文件系统非常相似,每个节点称作 znode,本身包含数据,还可以拥有子节点。
客户端以TCP连接一台节点,该节点故障时,客户端会切换至其他节点。
客户端可以订阅某些节点的事件(watcher机制),当节点内容或其子节点有变化时,客户端会收到通知。

  • 高性能:多读少写的情况下,速度很快;存储于内存中,并有持久存储中的事务日志和快照;
  • 高可用性(无中心化结构可避免单点故障): 个别节点故障不影响整体使用;
  • 监视机制: 客户端可以监视一个结点(node),当结点断开或有修改时,客户端会收到通知;
  • 顺序一致性: 来自客户端的更新将按照它们发送的顺序进行应用。
  • 原子性: 保证数据完整、一致,更新成功或失败,没有部分结果。
  • 单系统映像: 无论服务器连接到哪个服务器,客户端都会看到相同的服务视图。
  • 可靠性: 一旦更新被应用,它将一直持续到客户覆盖更新。
  • 及时性: 系统的客户观点在一定的时间范围内保证是最新的。

1.3 系统要求

ZooKeeper 以 Java 版本运行,Java 版本要求为 1.6+;
支持的操作系统包括: GNU/Linux, Solaris, FreeBSD, Windows。

2.Linux 下安装

https://zookeeper.apache.org/doc/current/zookeeperStarted.html

2.1 下载并解压(35M)

1
2
3
4
5
6
7
# https://archive.apache.org/dist/zookeeper/
# https://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/zookeeper-3.4.11.tar.gz
sudo rm -rf /opt/zookeeper-3.4.11
sudo tar -zxf zookeeper-3.4.11.tar.gz -C /opt
sudo chown -R root:root /opt/zookeeper-3.4.11
sudo rm -rf /opt/zookeeper-3.4.11/bin/*.cmd

2.2 设置环境变量

1
2
3
## sudo vim /etc/profile ## 所有用户有效
export ZOOKEEPER_HOME=/opt/zookeeper-3.4.11
export PATH=$PATH:$ZOOKEEPER_HOME/bin

文件保存后,Linux用户重新登录后生效。

2.3 准备目录与配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# sudo vim $ZOOKEEPER_HOME/bin/zkInit.sh
# sudo -E sh $ZOOKEEPER_HOME/bin/zkInit.sh
for INDEX in {1..3}; do
sudo rm -rf $ZOOKEEPER_HOME/{data,logs}/$INDEX
sudo mkdir -p $ZOOKEEPER_HOME/{data,logs}/$INDEX
echo $INDEX | sudo tee $ZOOKEEPER_HOME/data/$INDEX/myid > /dev/null

# zoo.cfg 参考: grep -v "^#" $ZOOKEEPER_HOME/conf/zoo_sample.cfg
cat > $ZOOKEEPER_HOME/conf/zoo-$INDEX.cfg << EOF
tickTime=2000 ## ZooKeeper 的最小时间单位(ms)
initLimit=10 ## 投票选举新 leader 的初始化时间(以 tickTime 为单位)
syncLimit=5 ## Leader 检测 Follower 可用性心跳的超时时间(以 tickTime 为单位)
clientPort=218$INDEX ## 客户端用来连接 ZooKeeper 的端口
dataDir=$ZOOKEEPER_HOME/data/$INDEX ## 数据目录(存储内存数据库快照)
dataLogDir=$ZOOKEEPER_HOME/logs/$INDEX ## 日志目录(存储事务日志)
server.1=localhost:2281:2291
server.2=localhost:2282:2292
server.3=localhost:2283:2293
EOF
done

其中的 clientPort=218$INDEX 是提供给客户端连接的端口(2181,2182,2183);
其中的 server.N = hostname : port1 : port2

  • N(1,2,3): “必须”是一个数字(表示这是第几号server),否则报错 java.lang.NumberFormatException: For input string: "xxx"
  • hostname(localhost): 是该 server 所在的域名或IP地址,为了通用,可替换为域名zk{n}.company.com 并在 hosts 里配置;
  • port1(2281,2282,2283): 当前 server 是 leader 时,监听此端口接受 followers 的连接,注意followers不会监听此端口(直到它升级为 leader)
  • port2(2291,2292,2293): 是选举 leader 时所使用的端口。

必须生成文件 $ZOOKEEPER_HOME/data/%n/myid,其内容为 zoo.cnf 中的 N(服务器ID), 否则抛出异常 java.lang.IllegalArgumentException: $ZOOKEEPER_HOME/data/{n}/myid file is missing

2.4 服务的配置并启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
## sudo vim /usr/lib/systemd/system/zookeeper@.service
## 其中的 %i 将来会被替换为具体的 1/2/3
[Unit]
Description=ZooKeeper
After=syslog.target network.target

[Service]
Type=forking
Environment="ZOOCFG=zoo-%i.cfg"
ExecStart=/opt/zookeeper-3.4.11/bin/zkServer.sh start
ExecStop=/opt/zookeeper-3.4.11/bin/zkServer.sh stop

[Install]
WantedBy=multi-user.target

配置为自动启动,并立即启动:

1
2
3
4
5
sudo systemctl daemon-reload
sudo systemctl enable zookeeper@{1,2,3}
sudo systemctl start zookeeper@{1,2,3}
sudo netstat -natp | grep LISTEN | grep -E "218|228|229"
# sudo systemctl stop zookeeper@{1,2,3}

2.5 防火墙放行

如果非本机应用需要连接 ZooKeeper,必须把所有 clientPort 端口放行。

1
2
3
4
5
### sudo vim /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 2181 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 2182 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 2183 -j ACCEPT
### 重启生效: sudo systemctl restart iptables

2.6 客户端验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
zkCli.sh -server localhost:2181 ## 进入命令行状态
help ## 显示所有命令格式
quit ## 退出命令行状态
history ## 显示历史命令

ls path [watch]
createpath data acl
delete path [version]
set path data [version]
get path [watch]
stat path [watch]
sync path

listquota path
setquota -n|-b val path
delquota [-n|-b] path

addauth scheme auth
setAcl path acl
getAcl path

printwatches on|off
redo cmdno

也可集连接和命令于一行:
zkCli.sh -server localhost:2181 ls /

2.7 清空数据【慎用】

1
2
3
sudo systemctl stop zookeeper@{1,2,3}
sudo rm -rf $ZOOKEEPER_HOME/{logs,data}/{1,2,3}/version-*
sudo systemctl start zookeeper@{1,2,3}

2.8 卸载服务【慎用】

1
2
3
sudo systemctl stop zookeeper@{1,2,3}
sudo systemctl disable zookeeper@{1,2,3}
sudo rm -rf $ZOOKEEPER_HOME

3.Windows 下安装(可用于开发)

3.1 下载

https://archive.apache.org/dist/zookeeper/
https://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/
https://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/zookeeper-3.4.11.tar.gz

3.2 安装

3.2.1 解压

3.2.2 修改系统环境变量

1
2
set ZOOKEEPER_HOME={???}\zookeeper-3.4.11
set PATH=%ZOOKEEPER_HOME%\bin

3.2.3 修改 conf\zoo-%n.cfg

1
2
3
4
5
6
7
cd/d %ZOOKEEPER_HOME%
del /q bin\*.sh
rd/s/q data logs
for %n in (1,2,3) do @mkdir logs\%n
for %n in (1,2,3) do @mkdir data\%n
for %n in (1,2,3) do @echo %n> data\%n\myid
for %n in (1,2,3) do @copy/b conf\zoo_sample.cfg conf\zoo-%n.cfg

修改文件 conf\zoo-%n.cfg 如下(分别替换其中的 %n 为 1,2,3):

1
2
3
4
5
6
7
8
9
tickTime=2000
initLimit=10
syncLimit=5
clientPort=218%n
dataDir=D:/Software/Architecture/zookeeper-3.4.11/data/%n
dataLogDir=D:/Software/Architecture/zookeeper-3.4.11/logs/%n
server.1=localhost:2281:2291
server.2=localhost:2282:2292
server.3=localhost:2283:2293

参数说明与 Linux 中相关内容一样。

3.2.4 修改脚本

删除 bin\zkEnv.cmd 中的 set ZOOCFG=%ZOOCFGDIR%\zoo.cfg 一行;

1
for %n in (1,2,3) do @copy/b bin\zkServer.cmd bin\zkServer%n.cmd

修改各个文件 zkServer%n.cmdcall "%~dp0zkEnv.cmd" 之前加一行:
set ZOOCFG=%~dp0%..\conf\zoo-%n.cfg,注意替换 %n 分别为 1/2/3

3.3 启动服务

1
2
3
zkServer1.cmd
zkServer2.cmd
zkServer3.cmd

3.4 客户端验证

1
2
3
zkCli.cmd -server centos:2181 ## 连接 Linux 上服务
zkCli.cmd -server localhost:2181 ## 连接本机上服务
## 更多内容参见前面 Linux 中相应部分

4.集群部署(生产环境)

管理员指南: https://zookeeper.apache.org/doc/current/zookeeperAdmin.html

  • 要求至少为三台 ZooKeeper 服务器,最好是奇数个服务器(以便多数正常机器处理少数机器的故障),通常三台足够了,如果想更可靠,可增加至五台;
  • 为避免各服务器同时发生故障,最好部署在不同机器、不同网络交换机(电路、冷却系统等)、甚至不同机房;
  • 为避免内存交换,要设置足够大的 JVM 堆,比如 4G 机器可指定 3G;
文章目录
  1. 1.概述
    1. 1.1 ZAB协议
      1. 1.1.1 领导选举(Leader Election)
      2. 1.1.2 信息同步(Atomic broadcast)
    2. 1.2 内部原理
    3. 1.3 系统要求
  2. 2.Linux 下安装
    1. 2.1 下载并解压(35M)
    2. 2.2 设置环境变量
    3. 2.3 准备目录与配置文件
    4. 2.4 服务的配置并启动
    5. 2.5 防火墙放行
    6. 2.6 客户端验证
    7. 2.7 清空数据【慎用】
    8. 2.8 卸载服务【慎用】
  3. 3.Windows 下安装(可用于开发)
    1. 3.1 下载
    2. 3.2 安装
      1. 3.2.1 解压
      2. 3.2.2 修改系统环境变量
      3. 3.2.3 修改 conf\zoo-%n.cfg
      4. 3.2.4 修改脚本
    3. 3.3 启动服务
    4. 3.4 客户端验证
  4. 4.集群部署(生产环境)