ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Zookeeper集群搭建超详细步骤:三节点高可用实战

2026/9/29 8:19:51 拓冰建站 浏览量
Zookeeper集群搭建超详细步骤:三节点高可用实战 Zookeeper集群搭建步骤越详细越好照着做就行做分布式系统的人基本绕不开zookeeper。Zookeeper是分布式协调服务选主、配置管理、分布式锁、注册中心很多底层能力都靠它。你在生产环境里直接部署单机zookeeper基本上等于给自己埋雷——节点一挂整个依赖它的业务链路就全断了。所以搭建一套可用的zookeeper集群是入门大数据和分布式系统绕不过去的第一步。这篇文章我会直接带你把一个三节点zookeeper集群完整搭起来。从环境准备、配置文件说明到启动验证、故障排查全部细节都摆出来按照步骤走就能跑通。1. 集群模式与整体设计思路1.1 为什么一定要用集群Zookeeper本身是个分布式协调组件它存在的意义就是为其他分布式系统提供高可用的协调能力。如果zookeeper自己是单点那协调层就变成了整个系统里最脆弱的一环这显然不合理。而且从zookeeper的实现机制来看它是一个基于内存数据模型、通过ZAB协议复制状态的服务如果只部署一个节点这个节点的存活状态直接决定了所有依赖它的服务是否可用。搭建zookeeper集群最核心的目的是解决单点故障问题。当某一台机器挂掉的时候剩下的节点还能继续对外提供服务业务不会中断。另一个原因在于zookeeper只有集群模式下才能暴露真正的选举、过半提交、数据同步等核心机制伪集群和单机版都只是开发调试用的。我们在实际项目中通常把zookeeper部署为3台或5台机器。选择三台不是拍脑袋决定的这和zookeeper的过半机制直接相关。任何写入操作需要过半节点确认才能提交成功也就是2台。只要Cluster里还有两台存活整个集群就能正常工作。如果只有2台机器挂掉一台剩余1台无法构成过半整个集群就废了。3台机器能允许1台故障5台能允许2台故障故障容忍能力是没有本质区别的所以追求性价比的生产环境通常选择3节点追求更高可用性的会选5节点。1.2 集群部署的三种模式对比很多人第一次接触zookeeper集群时会混淆单机模式、伪集群模式和集群模式这三个概念。它们虽然在部署步骤上有相似之处但本质上完全不同。单机模式非常简单就是在一台机器上跑一个zookeeper进程配置都不用怎么动。这种模式适合学习API和快速原型验证不适合任何生产场景。伪集群模式是在一台物理机器上启动多个zookeeper进程每个进程用不同的端口和不同的数据目录。这种模式能模拟出集群的选举和数据同步过程但因为没有真正的网络隔离一旦机器本身挂掉所有伪节点一起失效所以它只适合本机模拟实验验证一下配置是否有错。真正的集群模式则是把zookeeper分布到多台物理机器上每个节点独立运行通过网络通信协作这才是生产环境的正确形态。这里有个特别要注意的点伪集群中多个进程共享同一台机器的CPU、内存和磁盘资源即使配置看起来没问题也无法模拟网络分区、机器断电这类真实故障所以用它验证出来的高可用效果是不真实的。1.3 三节点集群的整体架构本文搭建的三节点zookeeper集群整体规划如下三台服务器分别承担一个zookeeper节点节点之间通过两个端口通信。端口2181用于客户端连接2888端口用于follower与leader之间的数据同步3888端口用于leader选举阶段的投票通信。也就是说每个zookeeper进程在Linux上实际会监听三个端口排查端口占用问题时要注意这一点。整个集群部署过程中最核心的机制是选举和过半提交。启动时每个节点都会先进入LOOKING状态然后通过3888端口互相通信进行投票票数过半的节点当选为Leader。日常运行中写请求统一由Leader处理Leader写入成功后会将事务广播给所有Follower当收到过半Follower的确认后再向客户端返回成功。理解了这两个机制后面配置文件中很多参数的含义就自然清晰了。2. 环境准备与系统规划2.1 服务器规划与操作系统要求搭建zookeeper集群我建议直接准备三台Linux服务器比如虚拟机、云主机或者物理机都可以。操作系统选择CentOS 7或Ubuntu 20.04这类主流版本都行核心注意点是三台机器的系统架构保持一致否则一些底层操作可能会出问题。绝不要用Windows服务器做生产级zookeeper集群虽然zookeeper本身支持Windows但很多企业生产环境的管理工具、权限模型、网络配置在Windows上都会遇到额外麻烦。三台机器的IP和角色规划可以参考这个表格服务器IP地址节点角色操作系统node1192.168.1.101zookeeper节点CentOS 7node2192.168.1.102zookeeper节点CentOS 7node3192.168.1.103zookeeper节点CentOS 7以上IP地址只是示例实际环境中你需要按照自己的网段来调整。但有一点很关键这三台机器之间需要保证网络互通并且生产环境中不要跨机房或跨城市部署同一个zookeeper集群因为网络延迟会严重影响ZAB协议的数据同步效率和选举速度。2.2 JDK环境安装Zookeeper是Java写的所以运行环境里必须要有JDK。版本方面建议使用JDK 1.8及以上zookeeper3.6.x要求JDK1.8是底线如果你用zookeeper3.7以上版本建议直接用JDK11或JDK17。在每台机器上先检查是否已安装Java敲下面的命令java -version如果提示找不到命令就需要先安装JDK。CentOS 7上可以用yum直接装yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel装完再验证一下版本。我自己的习惯是安装OpenJDK而不是Oracle JDK因为两者的API基本一致而OpenJDK的版本更新和安全补丁更及时日常使用完全没区别。生产环境里除非你的项目有特殊要求否则OpenJDK是更稳妥的选择。2.3 配置主机名与hosts映射三台机器之间是通过主机名来互相识别的zookeeper的配置文件中会用到server.1node1:2888:3888这种写法。所以每台机器都要配置好主机名并且hosts文件中要互相加入三台机器的IP映射。以node1为例设置主机名hostnamectl set-hostname node1然后编辑/etc/hosts文件把三台机器的映射都加进去192.168.1.101 node1 192.168.1.102 node2 192.168.1.103 node3三台机器都需要执行同样的hosts配置这样每台机器都能通过主机名访问另外两台。注意很多zookeeper报无法解析主机名的错误基本都是hosts没有配置好或者IP换过之后hosts缓存没清除导致的。修改hosts后最好执行一下ping node1确认OK再继续往下走。2.4 关闭防火墙或开放端口三台服务器上的zookeeper节点之间需要通信客户端也要连接2181端口所以必须保证相关端口畅通。最简单的做法是关闭防火墙但生产环境里更推荐只放行指定端口。如果你在测试环境图省事可以这样systemctl stop firewalld systemctl disable firewalld生产环境则建议用iptables或firewalld放行这三个端口以firewalld为例firewall-cmd --permanent --add-port2181/tcp firewall-cmd --permanent --add-port2888/tcp firewall-cmd --permanent --add-port3888/tcp systemctl reload firewalld这一步强烈建议在搭建之前就完成否则后面启动集群时会遇到客户端连接超时、节点无法相互同步等各种诡异问题排查起来非常浪费时间。2.5 时间同步配置Zookeeper对时间戳的精确性比较敏感虽然它不是严格意义上的强一致时间服务但节点之间的时钟偏移过大会影响事务ID和会话超时判断进而导致分布式场景下的各种异常。很多人在集群搭建初期忽略了时间同步等到运行一段时间后才发现Leader频繁切换查下来就是时钟偏移严重导致的。集群内的时间同步推荐使用NTP服务。CentOS 7默认安装了chrony我们可以直接使用它systemctl start chronyd systemctl enable chronyd配置好NTP源后可以查看时间同步状态timedatectl或者执行chronyc sources -v查看具体的同步源情况。确保三台机器的时间差控制在1秒以内再进入下一步。3. 集群配置文件详解与核心参数说明3.1 下载与解压安装进入官网下载页找到稳定版本的zookeeper二进制压缩包。以zookeeper 3.6.3版本为例在每台服务器上执行cd /opt wget https://archive.apache.org/dist/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz tar -zxvf apache-zookeeper-3.6.3-bin.tar.gz mv apache-zookeeper-3.6.3-bin /opt/zookeeper这里要提醒一下下载时一定要选择-bin后缀的包不带bin的源码包是不能直接运行启动脚本的。这个坑我已经看到很多人踩过了下载源码包后会发现bin目录下根本没有需要的启动shell脚本。3.2 创建数据目录每个zookeeper节点都需要一个数据目录用来存放快照日志和myid文件。数据目录不要放在临时目录下建议放在独立的磁盘分区。在生产环境中最好为zookeeper单独挂载一块磁盘因为zookeeper的写性能直接受磁盘I/O影响如果和系统盘抢I/O在高并发下很容易出现同步延迟。创建数据目录mkdir -p /data/zookeeper3.3 修改zoo.cfg配置文件进入zookeeper的conf目录把默认的zoo_sample.cfg复制为zoo.cfgcd /opt/zookeeper/conf cp zoo_sample.cfg zoo.cfg然后用vim编辑zoo.cfg文件最重要的是下面几个参数tickTime2000 initLimit10 syncLimit5 dataDir/data/zookeeper clientPort2181 server.1node1:2888:3888 server.2node2:2888:3888 server.3node3:2888:3888每个参数的含义都值得仔细理解一下后面排障时会用到tickTime是zookeeper中最基本的时间单位单位是毫秒。默认值是2000也就是2秒。它用于心跳超时和会话超时的计算。其他与时间相关的参数都以tickTime的倍数来计算。initLimit是follower初始连接时同步时间的限制单位是tickTime的倍数。配置为10表示follower与leader之间的初始连接和数据同步最多允许10个tickTime的时间也就是20秒。如果集群数据量很大可以适当调大这个值否则follower追赶数据时容易超时。syncLimit是follower与leader之间请求和应答的超时时间同样是tickTime的倍数。配置为5表示10秒内如果follower没有收到leader的响应就认为leader已经失联并重新发起选举。如果把集群部署在网络不稳定的环境中可以适当调大这个值。dataDir是zookeeper存储快照文件的目录必须和前面创建的目录保持一致。这个目录如果不存在zookeeper启动会直接失败。clientPort是客户端连接zookeeper时使用的端口默认是2181一般情况下不需要改动。server.1、server.2、server.3这三行是关键中的关键。它的格式是server.Ahost:port1:port2A是节点的myid值host是该节点的机器名或IPport1是follower连接leader时使用的通信端口port2是选举时使用的通信端口。也就是说每个节点在配置文件中要把集群中所有节点的信息都写进去而不是只写自己的。3.4 创建myid文件zoo.cfg中server.1node1这种写法意思是myid为1的节点运行在node1上。但zookeeper如何知道当前机器是哪个节点呢它通过dataDir目录下的myid文件来识别。在node1上执行echo 1 /data/zookeeper/myid在node2上执行echo 2 /data/zookeeper/myid在node3上执行echo 3 /data/zookeeper/myid三个节点的myid文件内容各不相同必须和zoo.cfg里server.A后面的A值保持一致。节点1对应server.1myid就是1。节点2对应server.2myid就是2。节点3对应server.3myid就是3。这是整个集群搭建中最容易踩坑的地方。三台机器的myid如果相同或者myid的值在zoo.cfg中没有对应的server配置启动时就会报Invalid myid错误。检查的时候先看zoo.cfg再确认myid文件基本能解决80%的启动失败问题。3.5 其他重要配置项除了上面这些核心配置项有经验的运维人员通常还会在zoo.cfg里再加几个实用的配置maxClientCnxns60 autopurge.snapRetainCount3 autopurge.purgeInterval1maxClientCnxns用来限制单台服务器上允许的最大客户端连接数默认是60。如果你业务的连接数比较大可以适当调高但不要设置成00表示不限制反而容易因为连接数过多拖垮服务器。autopurge.snapRetainCount和autopurge.purgeInterval配合使用分别表示保留快照的数量和清理事务日志的间隔单位是小时。zookeeper运行时间长了之后dataDir下会积累大量快照文件和事务日志如果不清理会占满磁盘。生产环境建议开启自动清理保留最近3-5份快照即可。另外一个容易被忽略的配置是JVM内存。zookeeper默认的堆内存大小由bin目录下的zkServer.sh脚本控制默认的JVM参数比较保守只有几百MB到1GB。如果你的业务量较大可以修改脚本中的JVMFLAGS参数把最大和最小堆内存调大。修改方式是在zookeeper的bin目录下找到zkEnv.sh文件设置export JVMFLAGS-Xms2048m -Xmx2048m $JVMFLAGS注意这里不要直接改zkServer.sh因为启动时它会引用zkEnv.sh里的JVMFLAGS环境变量。调内存时也要遵循一个原则所有节点的内存配置保持一致避免因为单个节点内存配置不同导致选举出的Leader性能瓶颈。4. 集群启动、初始化与状态验证4.1 三台节点的启动顺序执行启动命令时很多人习惯一台一台启动然后立刻查看状态结果发现后面启动的节点报一堆连接异常就开始慌了。这里先说明一下zookeeper集群的启动不需要严格按顺序来只要三个节点最终都完成启动集群就会自动选出Leader。但为了让整个初始化过程更清晰建议按照node1、node2、node3的顺序依次启动。在三台机器上分别执行/opt/zookeeper/bin/zkServer.sh start启动后可以先看一下进程是否已经运行jps正常情况下每台机器上都能看到QuorumPeerMain进程。进程名是QuorumPeerMain这是zookeeper 3.x版本以来的主进程类名看到它基本说明启动流程走通了。4.2 查看集群状态与角色分配启动完成之后可以执行状态查询命令/opt/zookeeper/bin/zkServer.sh status输出的结果会明确告诉你当前节点是Leader还是Follower。例如node1上看到ZooKeeper JMX enabled by default Using config: /opt/zookeeper/bin/../conf/zoo.cfg Client port found: 2181. Client address: localhost. Mode: leadernode2和node3上看到Mode: follower说明选举已经完成集群就绪。初次启动时三个节点会相互竞争最终通过ZAB协议选择出一个Leader。如果此时个别节点显示Mode: standalone说明集群配置有问题它降级成了单机模式这时候要去检查zoo.cfg中的server配置以及myid文件。Mode显示为standalone是最常见的一个坑后面我会专门讲。4.3 通过客户端命令验证集群功能角色确认好的基础上再用客户端连接验证一下读写是否正常。在任意一台机器上执行/opt/zookeeper/bin/zkCli.sh -server 192.168.1.101:2181客户端连接成功后先创建一个节点create /test_cluster hello然后读取这个节点get /test_cluster如果输出包括节点路径和内容说明客户端的写入和读取都正常。接下来再到另一台节点上执行get /test_cluster也能读到同样的内容说明数据已经在集群内完成了同步。最后退出客户端quit4.4 模拟故障验证集群高可用集群搭建完不验证一下高可用能力总觉得不踏实。这里建议做一个简单的故障演练来验证三节点集群是否真正达到了高可用目标。比如在node1这个Leader节点上执行kill -9 QuorumPeerMain进程号然后观察集群状态。过几秒后在node2上执行/opt/zookeeper/bin/zkServer.sh status正常情况下node2或node3会被重新选举为Leader集群对外服务并没有中断。这时再去连接客户端依然可以正常读写数据。这说明三节点zookeeper集群配置成功并且具备了标准的故障转移能力。生产环境中最好把zookeeper纳入到监控系统中比如用Prometheus和Grafana采集zookeeper的metrics指标当节点异常退出时能第一时间收到告警而不需要等业务方反馈。5. 高频问题排查与操作避坑5.1 模式变成standalone的诡异问题很多人在刚启动完集群后用zkServer.sh status查看状态发现输出是Mode: standalone而不是leader或follower。出现这种情况先不要怀疑配置对照下面的排查思路逐一检查。首要是确认每台机器的zoo.cfg是否都写入了完整的server配置。如果某台机器只保留了本机的server配置而漏掉了其他节点它启动后就会认为集群里只有自己一个节点所以降级为standalone模式。其次是检查myid文件如果myid文件不存在或者内容与zoo.cfg不对应节点同样无法参与集群组网。最后检查SELinux状态CentOS 7默认开启的SELinux会阻止非标准端口的访问在没有关闭防火墙的情况下SELinux也会干扰集群节点之间的通信导致节点之间互相发现不了对方从而各自进入standalone状态。我个人遇到过最匪夷所思的一次就是SELinux导致的standalone问题。排查了配置文件、hosts、防火墙最后发现是SELinux把2888和3888端口给拦了。如果其他都排除了不妨执行setenforce 0临时关闭SELinux试试。5.2 客户端连接超时但服务端看起来正常客户端连接zookeeper集群超时服务端日志又没有明显异常这种情况多数是网络层面的问题。先检查2181端口是否对外开放了其次确认客户端所在机器到服务端机器的网络路径是否畅通。用telnet验证一下端口是很直接的方法telnet 192.168.1.101 2181如果看到Connected to 192.168.1.101的提示说明端口可达。另外还要检查客户端连接的IP是不是正确配置了hosts的环境中如果客户端解析到的是旧IP同样会出现连接超时。还有一点容易被忽略zookeeper对连接数有限制配置文件里maxClientCnxns默认值如果太小大量客户端同时接入时会报Connection refused或者连接被重置这时候需要调大maxClientCnxns。5.3 事务日志清理与磁盘满的问题zookeeper默认会在dataDir下不断积累data目录下的version-2目录里面存放着快照文件和事务日志。运行一段时间后发现磁盘爆满这是非常常见的情况。虽然前面配置了autopurge但自动清理只对超出阈值的文件生效如果业务写入量极大自动清理的速度可能跟不上产生速度。一个更稳妥的管理方式是把事务日志目录和数据快照目录分开存放。生产环境中可以将dataLogDir单独指向一块独立的磁盘例如在zoo.cfg中添加dataLogDir/data/zookeeper_log这样做的目的是事务日志是顺序I/O写盘快照文件是随机I/O两者混在一起容易互相干扰。把日志分离到独立磁盘可以提高写入性能也有助于单独管理磁盘空间。同时用crontab定时清理过期的日志文件比如只保留最近7天的find /data/zookeeper/version-2 -name log.* -mtime 7 -exec rm {} \;5.4 常用问题与处理措施速查表下面是把高频问题、现象和解决建议整理成一张表格方便排查时快速定位问题。故障现象可能原因解决措施启动报Invalid myidmyid文件缺失或内容错误检查/data/zookeeper/myid确保与zoo.cfg中server.A编号一致Mode显示为standalonezoo.cfg缺少完整server配置SELinux阻断通信补齐server配置检查防火墙与SELinux状态节点间心跳超时syncLimit设置过小网络不稳定适当调大syncLimit参数检查交换机链路质量客户端Connection refused2181端口未开放或服务未启动检查防火墙放行规则确认QuorumPeerMain进程存在磁盘持续增长快照与事务日志未清理启用autopurge定期清理version-2下过期日志选举频繁切换Leader系统时钟偏移GC停顿时间长配置NTP时间同步优化JVM参数减少GC暂停5.5 关于监控与日常巡检的补充集群搭建完成只是第一步日常运维最怕的是集群看起来正常实则问题正在酝酿。我的习惯是每天巡检三个指标进程是否存在、端口是否能连通、集群角色是否正常。用一行命令可以快速检查echo ruok | nc 127.0.0.1 2181zookeeper支持一个四字命令ruok执行后返回imok就说明当前节点健康。常用的四字命令还有stat、mntr、srvr等其中mntr返回的监控指标非常丰富适合脚本化采集。配合一个简单的脚本几秒钟就能过一遍所有节点。生产环境的zookeeper集群还建议加入Prometheus生态来监控zookeeper的metrics可以通过JMX方式导出再配合Grafana面板展示。告警规则重点盯以下几个指标节点数是否少于预期、Leader是否频繁切换、平均请求延迟是否持续走高、文件描述符使用率是否接近上限。6. 集群落地的几个小建议6.1 版本选择与升级策略如果你准备从零开始搭一套新的zookeeper集群建议优先选择3.6.x或3.7.x的版本。3.4系列已经非常老很多新特性没有3.8以上版本虽然也有但目前社区生态中的组件适配度需要额外验证。集群搭建好之后没有特别强烈的需求不要频繁升级因为zookeeper的升级需要逐台滚动重启期间虽然能对外提供服务但操作稍有不慎就可能引发选举风暴。6.2 与其他组件集成时的注意事项zookeeper集群本身搭好之后通常是为了支撑其他分布式组件。如果你是在为Kafka集群服务要注意broker端设置的zookeeper连接串必须是完整的IP:2181,IP:2181,IP:2181格式而且各组件的时间配置要在同一个水平线上。如果是为HBase服务需要注意HBase的根目录节点和zookeeper的namespace不能冲突。如果是给Dubbo或Spring Cloud服务做注册中心要关注会话超时时间与服务心跳周期的匹配关系避免服务因为短暂的GC停顿就被判定下线。6.3 最后补充一个小技巧最终整个集群跑通之后建议在zookeeper的数据目录中把zoo.cfg也备份一份内容与conf目录保持一致。这样将来排查问题或者机器迁移时即使conf目录意外丢失也能通过数据目录的备份快速恢复配置。另外三台机器的zoo.cfg内容要完全一致不要因为某台机器承担的角色不同而单独修改配置否则后续维护成本会非常高。Zookeeper集群的搭建本身并不复杂通过一次完整的实操把配置项理解了、把启动流程走熟了后面你再去搭Kafka集群、Hadoop集群都会有一种轻车熟路的感觉。希望这篇超详细的步骤记录能帮你少踩几个坑。如果你在实际搭建中遇到其他奇怪的问题欢迎在评论区描述你的zoo.cfg和启动报错信息我看到后会帮你一起分析。