刚接触 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),并确保它们之间网络互通。以下是本次实践使用的节点信息:

IPHostname
192.168.42.140zookeeper1
192.168.42.145zookeeper2
192.168.42.146zookeeper3

首先,为每台机器设置主机名并配置 hosts 文件,这样节点之间可以通过主机名互相访问,避免 IP 变更带来的麻烦。

hostnamectl set-hostname zookeeper1  //修改hostname
hostname  //查看hostname
image-20251204153434057image-20251204153539525image-20251204153551879

⚠️ 关键提醒:主机名不要包含下划线或特殊字符,否则可能导致 ZooKeeper 解析失败。

三节点统一环境配置

以下操作需要在三台虚拟机上分别执行,确保环境一致。

关闭防火墙与 SELinux

ZooKeeper 集群节点间通过 2181(客户端端口)、2888(通信端口)、3888(选举端口)进行通信。防火墙必须放行这些端口,或者直接关闭防火墙(测试环境推荐)。

systemctl stop firewalld    //停止firewalld防火墙
systemctl disable firewalld   //disable防火墙,使其开机不自启
systemctl status firewalld    //查看firewalld是否已经关闭
image-20251204153720707

同时,修改 SELinux 配置为 disabled:

vi /etc/sysconfig/selinux
image-20251204153820960

配置静态 IP 与主机映射

为了避免 DHCP 导致 IP 变化,建议为每台机器配置静态 IP。首先查看网卡名称和 MAC 地址:

vi /etc/sysconfig/network-scripts/ifcfg-ens33
image-20251204154615776

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

192.168.42.140 zookeeper1
192.168.42.145 zookeeper2
192.168.42.146 zookeeper3
image-20251204155338255

✅ 完成上述步骤后,使用 ping zookeeper1 测试三台机器之间的连通性。

ZooKeeper 安装与单机验证

在三台机器上分别安装 ZooKeeper。首先确保 JDK 环境(Java 8 或以上)已就绪:

java -version
149b1d82094224db59959c7d7c10b8c8

从 Apache 官网下载 ZooKeeper 二进制包,上传到服务器并解压:

dd0fa6d9d8c3be9ae8d48cba0d9e2381
tar -zxvf apache-zookeeper-3.7.1-bin.tar.gz
d02b62095642e432bb7e77eb069401b5

为方便管理,重命名目录:

mv apache-zookeeper-3.7.1-bin/ zookeeper
328f816e419fefa040579c2deb731fa0

进入 conf 目录,复制配置文件模板:

mv zoo_sample.cfg zoo.cfg
a513c5c58d43e5e8f1b2f23c9cb67dd2

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

mkdir zkData
f606f45cb3374302bfa3c93f53b72300
vim zoo.cfg
8c29ef2a142f497bfc4ad80ea0fd03f0

启动单机 ZooKeeper 进行验证:

./zkServer.sh start
b165240c1b5d76c1ef38b5eb80f5435e

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

jps
b165240c1b5d76c1ef38b5eb80f5435e

启动客户端测试连接:

bin/zkCli.sh
183801c4d401c70b746141db86804128

退出客户端并停止服务:

quit
de0533544db1e1ae509bbc2742ff1ffe
./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
image-20251204160155080image-20251204160122040

⚠️ 踩坑点:server 列表中的 IP 地址必须写对,端口 2888 用于节点间数据同步,3888 用于选举投票。三台机器的 zoo.cfg 内容必须完全一致。

接下来,在 dataDir 目录中创建 myid 文件,内容为节点编号(与 zoo.cfg 中的 server.N 对应):

vi myid
image-20251204160334456

重要:myid 文件不能有换行或空格,否则集群无法选举 Leader。

启动集群并验证

依次在三台机器上启动 ZooKeeper:

./zkServer.sh start

启动后,使用 ./zkServer.sh status 查看角色:

image-20251204161224379

如果看到一台显示 Leader,两台显示 Follower,说明集群搭建成功。 恭喜你,现在拥有了一个高可用的 ZooKeeper 集群!

ZooKeeper 集群的简单使用

连接到任意节点,体验集群的强一致性特性:

./zkCli.sh -server 127.0.0.1:2181

查看根节点:

image-20251204162227722image-20251204165711393

创建不同类型的节点:

ls /
ls /zookeeper
create -e /znode01 001
create -e -s /znode02 002
create /znode03 003
create -s /znode04 004
ls /
image-20251204170044014

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

image-20251204170124456

查看和修改节点值:

get /znode03
image-20251204170213778
stat /znode03
image-20251204170310662
set /znode03 10086
image-20251204170356626

删除节点:

image-20251204170512533

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

image-20251204170723532image-20251204170748622image-20251204170759473

✅ 这验证了 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
image-20250814101639846

启动服务并检查状态:

sudo systemctl status cpolar
22e5adfaf290a17fc3384bb296055259

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

8a6698b1bf26d64ba3645827fbfb1c29

配置 TCP 隧道

在 Cpolar 管理界面创建隧道:

image-20251205112010088

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

image-20251205112023894

现在,你可以从任意设备连接 ZooKeeper:

./zkCli.sh -server 2.tcp.cpolar.top:10518
image-20251205143421041image-20251205143433382

固定 TCP 地址(可选)

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

image-20251205153835094

在隧道列表中修改配置:

编辑image-20251205155525955更新image-20251205155549999

最终得到固定的公网地址:

image-20251205155611969

测试连接:

./zkCli.sh -server 31.tcp.cpolar.top:11780
image-20251205155631474image-20251205155644311 [AFFILIATE_SLOT_1]

总结

从单机到集群,ZooKeeper 的部署模式决定了它能否胜任生产环境。本文详细演示了三节点集群的搭建步骤,并介绍了内网穿透工具 Cpolar 的使用方法。核心要点有三:

  • 集群必须奇数节点(推荐 3 或 5),确保 Leader 选举正常。
  • myid 文件与 zoo.cfg 必须严格对应,否则集群无法选举。
  • 防火墙放行 2181/2888/3888 端口,或直接关闭防火墙。

踩过的坑才是自己的经验。如果你正在使用 Kafka、HBase 或 Dubbo,请务必使用 ZooKeeper 集群,而不是单机玩具。

[AFFILIATE_SLOT_2]