刚接触 ZooKeeper 时,很多人和我一样,习惯在本地敲下 ./zkServer.sh start,连上 localhost:2181 就以为万事大吉。直到一次断电重启,临时节点全部消失、顺序计数器重置,才意识到——单机 ZooKeeper 只是个玩具,真正的生产环境必须依赖集群。本文结合真实踩坑经历,带你从头搭建一个三节点 ZooKeeper 集群,并分享内网穿透方案,助你在任意位置管理 ZooKeeper 服务。
为什么一定要用 ZooKeeper 集群?
单机 ZooKeeper 的致命缺陷在于:它不具备容错能力和数据持久性。一旦进程崩溃或机器重启,所有临时节点(Ephemeral)都会丢失,顺序节点(Sequential)的计数器也会重置。而集群模式通过 Zab 协议(ZooKeeper Atomic Broadcast)实现了强一致性和自动选主——当 Leader 节点故障时,其余 Follower 能在几秒内选举出新的 Leader,保证服务不中断、数据不丢失。
在 Kafka、HBase、Dubbo 等分布式系统中,ZooKeeper 承担着 Controller 选举、分区分配、配置管理 等核心职责,这些操作对一致性要求极高。以 Kafka 为例,如果 ZooKeeper 是单机,一旦宕机,整个 Kafka 集群将失去元数据管理能力,导致生产消费链路瘫痪。因此,三节点集群是生产环境的最低标配。
技术视角:ZooKeeper 的选举算法(Fast Leader Election)基于 Paxos 变体,要求集群中超过半数节点(即 2/3 个节点)存活才能正常工作。这也是为什么推荐奇数节点(如 3、5、7)的原因。
集群搭建前的环境准备
在开始之前,请准备三台 Linux 虚拟机(推荐 CentOS 7 或 Ubuntu 20.04),并确保它们之间网络互通。以下是本次实践使用的节点信息:
| IP | Hostname |
|---|---|
| 192.168.42.140 | zookeeper1 |
| 192.168.42.145 | zookeeper2 |
| 192.168.42.146 | zookeeper3 |
首先,为每台机器设置主机名并配置 hosts 文件,这样节点之间可以通过主机名互相访问,避免 IP 变更带来的麻烦。
hostnamectl set-hostname zookeeper1 //修改hostname
hostname //查看hostname



⚠️ 关键提醒:主机名不要包含下划线或特殊字符,否则可能导致 ZooKeeper 解析失败。
三节点统一环境配置
以下操作需要在三台虚拟机上分别执行,确保环境一致。
关闭防火墙与 SELinux
ZooKeeper 集群节点间通过 2181(客户端端口)、2888(通信端口)、3888(选举端口)进行通信。防火墙必须放行这些端口,或者直接关闭防火墙(测试环境推荐)。
systemctl stop firewalld //停止firewalld防火墙
systemctl disable firewalld //disable防火墙,使其开机不自启
systemctl status firewalld //查看firewalld是否已经关闭

同时,修改 SELinux 配置为 disabled:
vi /etc/sysconfig/selinux

配置静态 IP 与主机映射
为了避免 DHCP 导致 IP 变化,建议为每台机器配置静态 IP。首先查看网卡名称和 MAC 地址:
vi /etc/sysconfig/network-scripts/ifcfg-ens33

然后编辑网络配置文件,将 BOOTPROTO 改为 static,并添加 IP、网关、DNS 等信息。最后,在 /etc/hosts 中添加所有节点的映射关系:
192.168.42.140 zookeeper1
192.168.42.145 zookeeper2
192.168.42.146 zookeeper3

✅ 完成上述步骤后,使用 ping zookeeper1 测试三台机器之间的连通性。
ZooKeeper 安装与单机验证
在三台机器上分别安装 ZooKeeper。首先确保 JDK 环境(Java 8 或以上)已就绪:
java -version

从 Apache 官网下载 ZooKeeper 二进制包,上传到服务器并解压:
tar -zxvf apache-zookeeper-3.7.1-bin.tar.gz

为方便管理,重命名目录:
mv apache-zookeeper-3.7.1-bin/ zookeeper

进入 conf 目录,复制配置文件模板:
mv zoo_sample.cfg zoo.cfg

创建数据目录并修改 zoo.cfg 中的 dataDir:
mkdir zkData
vim zoo.cfg

启动单机 ZooKeeper 进行验证:
./zkServer.sh start

使用 jps 查看进程,确认 QuorumPeerMain 已运行:
jps

启动客户端测试连接:
bin/zkCli.sh


退出客户端并停止服务:
quit
./zkServer.sh stop
集群配置与启动
单机验证通过后,开始配置集群模式。首先配置环境变量,方便后续操作:
export ZK_HOME=/shan/zookeeper
export PATH=$PATH:$ZK_HOME/bin
修改 zoo.cfg,添加集群节点信息:
server.1=192.168.42.140:2888:3888
server.2=192.168.42.145:2888:3888
server.3=192.168.42.146:2888:3888


⚠️ 踩坑点:server 列表中的 IP 地址必须写对,端口 2888 用于节点间数据同步,3888 用于选举投票。三台机器的 zoo.cfg 内容必须完全一致。
接下来,在 dataDir 目录中创建 myid 文件,内容为节点编号(与 zoo.cfg 中的 server.N 对应):
vi myid

重要:myid 文件不能有换行或空格,否则集群无法选举 Leader。
启动集群并验证
依次在三台机器上启动 ZooKeeper:
./zkServer.sh start
启动后,使用 ./zkServer.sh status 查看角色:

如果看到一台显示 Leader,两台显示 Follower,说明集群搭建成功。 恭喜你,现在拥有了一个高可用的 ZooKeeper 集群!
ZooKeeper 集群的简单使用
连接到任意节点,体验集群的强一致性特性:
./zkCli.sh -server 127.0.0.1:2181
查看根节点:


创建不同类型的节点:
ls /
ls /zookeeper
create -e /znode01 001
create -e -s /znode02 002
create /znode03 003
create -s /znode04 004
ls /

断开服务后重新连接,观察临时节点消失、持久节点保留:

查看和修改节点值:
get /znode03
stat /znode03
set /znode03 10086

删除节点:

在 Leader 上创建节点,Follower 会自动同步:



✅ 这验证了 ZooKeeper 集群的 强一致性——所有节点数据最终一致。
内网穿透:让外部设备也能连接 ZooKeeper
在开发测试中,ZooKeeper 服务通常运行在内网虚拟机中(如 192.168.x.x),外部设备无法直接访问。此时,可以使用 Cpolar 实现内网穿透,将 ZooKeeper 的 2181 端口映射到公网地址。
./zkCli.sh -server 3.tcp.cpolar.io:12345
安装 Cpolar
在 ZooKeeper 所在机器上执行一键安装脚本:
sudo curl https://get.cpolar.sh | sh

启动服务并检查状态:
sudo systemctl status cpolar

浏览器访问 http://虚拟机IP:9200,使用 Cpolar 官网注册的账号登录:

配置 TCP 隧道
在 Cpolar 管理界面创建隧道:

创建成功后,获取公网地址:

现在,你可以从任意设备连接 ZooKeeper:
./zkCli.sh -server 2.tcp.cpolar.top:10518


固定 TCP 地址(可选)
免费版的公网地址每次重启会变化,如果需要固定地址,可以购买 Cpolar 的固定 TCP 套餐:


在隧道列表中修改配置:
编辑
更新
最终得到固定的公网地址:

测试连接:
./zkCli.sh -server 31.tcp.cpolar.top:11780

[AFFILIATE_SLOT_1]
总结
从单机到集群,ZooKeeper 的部署模式决定了它能否胜任生产环境。本文详细演示了三节点集群的搭建步骤,并介绍了内网穿透工具 Cpolar 的使用方法。核心要点有三:
- 集群必须奇数节点(推荐 3 或 5),确保 Leader 选举正常。
- myid 文件与 zoo.cfg 必须严格对应,否则集群无法选举。
- 防火墙放行 2181/2888/3888 端口,或直接关闭防火墙。
踩过的坑才是自己的经验。如果你正在使用 Kafka、HBase 或 Dubbo,请务必使用 ZooKeeper 集群,而不是单机玩具。
[AFFILIATE_SLOT_2]
浙公网安备 33010602011771号