Zookeeper 3.9.5 三节点高可用集群:Docker Compose 实战指南

分布式系统开发中,服务协调是核心挑战之一。作为Apache的顶级项目,Zookeeper已经成为分布式系统基础设施的重要组成部分。本文将带你从零开始,使用Docker Compose快速搭建一个生产可用的Zookeeper 3.9.5集群,并深入验证其高可用特性。

1. 环境准备与架构设计

在开始部署之前,我们需要明确几个关键概念。Zookeeper集群通常由奇数个节点组成(3、5、7等),这是为了满足"多数决"的选举机制。每个节点都需要有唯一的标识(myid),并且能够互相通信。

对于本次部署,我们选择3节点配置,这是生产环境中常见的平衡点——在保证高可用的同时,不会引入过多的资源开销。三个节点中,只要有两个节点存活,集群就能继续正常工作。

硬件要求建议

  • 每个节点至少1GB内存
  • 稳定的网络连接(节点间延迟应低于100ms)
  • 持久化存储(建议SSD)

提示:虽然可以在单机上模拟多节点集群用于测试,但生产环境强烈建议将节点部署在不同物理机上,避免单点故障风险。

2. Docker Compose 集群配置

下面是完整的docker-compose.yml文件,它定义了三个Zookeeper节点及其互联关系:

version: '3.8'

services:
  zoo1:
    image: zookeeper:3.9.5
    hostname: zoo1
    container_name: zoo1
    ports:
      - "2181:2181"
      - "2888:2888"
      - "3888:3888"
    environment:
      ZOO_MY_ID: 1
      ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
      ZOO_4LW_COMMANDS_WHITELIST: "*"
    volumes:
      - ./data/zoo1/data:/data
      - ./data/zoo1/datalog:/datalog

  zoo2:
    image: zookeeper:3.9.5
    hostname: zoo2
    container_name: zoo2
    ports:
      - "2182:2181"
      - "2889:2888"
      - "3889:3888"
    environment:
      ZOO_MY_ID: 2
      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181
      ZOO_4LW_COMMANDS_WHITELIST: "*"
    volumes:
      - ./data/zoo2/data:/data
      - ./data/zoo2/datalog:/datalog

  zoo3:
    image: zookeeper:3.9.5
    hostname: zoo3
    container_name: zoo3
    ports:
      - "2183:2181"
      - "2890:2888"
      - "3890:3888"
    environment:
      ZOO_MY_ID: 3
      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181
      ZOO_4LW_COMMANDS_WHITELIST: "*"
    volumes:
      - ./data/zoo3/data:/data
      - ./data/zoo3/datalog:/datalog

关键配置解析

配置项 说明 推荐值
ZOO_MY_ID 节点唯一标识 1-255之间的整数
ZOO_SERVERS 集群节点列表 server.id=host:port:port;client_port
ZOO_4LW_COMMANDS_WHITELIST 四字命令白名单 "*"表示允许所有
ports 端口映射 2181-2183对应客户端端口

3. 集群启动与验证

保存上述docker-compose.yml文件后,执行以下命令启动集群:

# 创建数据目录
mkdir -p ./data/{zoo1,zoo2,zoo3}/{data,datalog}

# 启动集群
docker-compose up -d

# 查看集群状态
docker-compose ps

等待约30秒让集群完成初始化后,我们可以验证集群状态:

# 检查节点1状态
docker exec -it zoo1 /bin/bash -c "zkServer.sh status"

# 检查节点2状态
docker exec -it zoo2 /bin/bash -c "zkServer.sh status"

# 检查节点3状态
docker exec -it zoo3 /bin/bash -c "zkServer.sh status"

正常情况下,输出应该显示一个Leader和两个Follower:

ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader

4. Leader选举验证与故障模拟

Zookeeper的核心价值在于其高可用性。让我们通过模拟节点故障来验证集群的自动恢复能力。

测试步骤

  1. 首先确定当前Leader节点(假设是zoo1)
  2. 停止Leader节点:
    docker-compose stop zoo1
    
  3. 观察剩余节点的日志:
    docker-compose logs -f zoo2 zoo3
    
  4. 约10秒后,检查新的Leader选举结果:
    docker exec -it zoo2 /bin/bash -c "zkServer.sh status"
    docker exec -it zoo3 /bin/bash -c "zkServer.sh status"
    
  5. 恢复zoo1节点并观察其重新加入集群:
    docker-compose start zoo1
    docker-compose logs -f zoo1
    

预期行为

  • 当Leader下线后,剩余节点会发起新一轮选举
  • 获得多数票的节点将成为新Leader
  • 原Leader恢复后会以Follower身份重新加入集群

5. 客户端连接与数据操作

集群验证通过后,我们可以通过客户端进行操作测试。Zookeeper提供了简单的命令行客户端:

# 连接到节点1
docker exec -it zoo1 zkCli.sh -server localhost:2181

# 创建测试节点
create /test "hello cluster"

# 从其他节点获取数据
docker exec -it zoo2 zkCli.sh -server localhost:2181 -e "get /test"

常用四字命令

  • stat :查看服务器状态
  • srvr :服务器详细信息
  • cons :客户端连接信息
  • mntr :监控统计信息

例如:

echo stat | nc localhost 2181

6. 生产环境优化建议

虽然我们的集群已经可以工作,但生产环境还需要考虑以下优化:

性能调优参数

参数 说明 生产建议
tickTime 心跳间隔 2000-4000ms
initLimit 初始化连接超时 10-20个tick
syncLimit 同步超时 5-10个tick
autopurge.snapRetainCount 保留的快照数 3-5
autopurge.purgeInterval 清理间隔 6-12小时

监控方案

  • 通过四字命令收集基础指标
  • Prometheus + Grafana监控体系
  • 关键告警项:
    • 节点角色变化
    • 连接数异常
    • 延迟升高

备份策略

  • 定期备份/data和/datalog目录
  • 考虑使用Zookeeper的snapshot机制
  • 测试备份恢复流程

7. 常见问题排查

在实际使用中,可能会遇到以下问题:

节点无法加入集群

  1. 检查myid文件是否正确
  2. 验证网络连通性(端口2888和3888)
  3. 查看日志中的选举相关错误

数据不一致

  1. 确认所有节点模式(Standalone/Replicated)
  2. 检查磁盘空间是否充足
  3. 验证时钟同步(NTP服务)

性能问题

  1. 分离数据和日志存储设备
  2. 调整JVM堆大小(建议不超过4GB)
  3. 优化snapshot策略

日志是排查问题的第一手资料,可以通过以下命令查看实时日志:

docker-compose logs -f

8. 集群扩展与升级

随着业务增长,可能需要扩展集群规模或升级版本。

扩展为5节点

  1. 在docker-compose.yml中添加两个新节点
  2. 更新所有节点的ZOO_SERVERS配置
  3. 确保新的myid不重复
  4. 滚动重启现有节点

版本升级步骤

  1. 备份所有数据
  2. 准备新版本的docker-compose.yml
  3. 逐个节点进行滚动升级
  4. 验证数据一致性和功能正常

重要提示:Zookeeper 3.5.x及以上版本支持动态配置,可以在不重启的情况下修改集群成员,但生产环境仍需谨慎操作。

在实际项目中,我们曾遇到一个有趣的案例:某次机房网络分区导致集群分裂,恢复后出现了数据不一致。通过分析事务日志和快照,最终确定了最新有效状态并手动恢复了服务。这提醒我们,分布式系统的运维不能完全依赖自动化,深入理解原理至关重要。

更多推荐