当前位置: 首页 > news >正文

Zookeeper 集群部署与故障转移

Zookeeper 介绍

Zookeeper 是一个开源的分布式协调服务,由Apache基金会维护,专为分布式应用提供高可用、强一致性的核心基础能力。它通过简单的树形命名空间(称为ZNode树)存储数据节点(ZNode),每个节点可包含少量数据和ACL权限控制。Zookeeper的核心价值在于解决分布式环境中的协同难题:如统一配置管理、分布式锁服务、集群选主、状态同步和命名服务等。其设计遵循CP原则(一致性优先),采用ZAB(Zookeeper Atomic Broadcast)共识协议保证数据强一致性,所有写操作必须由Leader节点协调,经集群多数节点(Quorum)确认后才能提交。客户端通过Session会话与集群交互,会话超时机制可自动清理临时节点(Ephemeral Nodes),而顺序节点(Sequential Nodes)生成的全局唯一路径则实现了分布式队列等高级模式。凭借其轻量级API、高吞吐和可靠的故障恢复机制,Zookeeper已成为Hadoop、Kafka、Dubbo等众多分布式系统的核心依赖。


Zookeeper 写请求处理

  • 客户端请求:客户端图标向Zookeeper集群发送写请求

  • Leader协调:其中一个节点接收请求,Leader将操作转换为事务Proposal

  • 广播提案:Leader向所有Follower广播提案

  • ACK确认:Followers处理提案后返回ACK,当收到多数节点ACK(如3/5节点)时,Leader发出COMMIT指令

  • 数据提交:所有节点将数据写入内存数据库,事务日志实时滚动记录

Zookeeper 事务日志和快照

Zookeeper 集群中的每个服务器节点每次接收到写操作请求时,都会先将这次请求发送给 leader。leader 将这次写操作转换为带有状态的事务,然后对这次写操作进行广播以便协调。当协调通过(即大多数节点允许这次写操作)后,leader 通知所有的服务器节点,使它们将这次写操作应用到内存数据库中,并将其记录到事务日志中。

当事务日志记录的次数达到一定数量后(默认 100,000 次),就会将内存数据库序列化一次,使其持久化保存到磁盘上。序列化后的文件称为“快照文件”。每次生成快照后,都会创建新的事务日志文件。


  1. 日志计数:事务日志计数器从0开始累加

  2. 触发阈值:当计数器达到snapCount=100,000时暂停新事务写入

  3. 序列化快照:内存数据库内容被序列化,生成快照文件

  4. 日志重置:创建新事务日志文件(旧日志归档,新日志从0开始计数)


Zookeeper 配置文件

tickTime=2000 # "滴答时间",用于配置Zookeeper中最小的时间单元长度(单位:毫秒),是其它时间配置的基础。
initLimit=10 # 初始化限制时间(包含启动和数据同步),单位是tickTime的倍数。
syncLimit=5 # 同步限制时间(用于正常工作状态下的心跳监测间隔),单位是tickTime的倍数。
dataDir=/tmp/zookeeper # 配置Zookeeper服务存储数据文件的目录供服务器访问。基于安全考虑,可以修改为 dataDir=/usr/local/zookeeper/data
#dataLogdir=/usr/local/zookeeper/logs # 可以指定事务日志的存储路径。事务日志对Zookeeper的性能影响非常大,强烈建议将事务日志目录(dataLogDir)和数据目录(dataDir)分开存储。
clientPort=2181 # 配置当前Zookeeper服务对外暴露的端口,供客户端连接和建立会话使用。
preAllocsize: # 为每个新的事务日志文件预分配磁盘空间的大小。默认是64M,意味着每个新的事务日志文件初始大小即为64M。如果Zookeeper产生事务(写操作)的频率非常高,可以考虑减小这个参数值,因为每次日志切换后都会创建一个新的事务日志文件(即使之前的64M空间可能尚未写满)。
snapCount: # 此配置项定义了Zookeeper在将内存数据库(DataTree)序列化为快照(Snapshot)文件之前,需要写入多少次事务日志。即,每写入若干次事务日志后,会生成一次快照。默认值为100000。为了防止Zookeeper集群中的所有服务器节点同时生成快照(通常情况下,所有集群节点的配置文件是完全相同的),当某个节点已写入的事务日志数量进入区间 (snapCount/2 + 1, snapCount) 时,会随机选择一个具体的数值作为该节点实际生成快照的触发点。
autopurge.snapRetainCount=3 # (3.4.0中新增的功能):启用Zookeeper自动清理功能后,此参数指定保留在 dataDir 和 dataLogDir 中的最新快照文件及其对应的事务日志文件的数量。系统将保留此数量的文件(默认为3,最小值也为3),并清除更旧的文件。
autopurge.purgeInterval=24 # (3.4.0及之后版本):此参数指定了自动清理功能执行的频率(单位:小时)。需要配置一个1或更大的整数。默认值是0,表示不开启自动清理功能。

Zookeeper 集群部署

现在有三台机器都已经安装Zookeeper

主机IP
Server1192.168.80.11
Server2192.168.80.22
Server3192.168.80.33

三台机器上传Zookeeper集群一键安装脚本

#!/bin/bash
ZK_VERSION=3.8.4
ZK_URL="https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-${ZK_VERSION}/apache-zookeeper-${ZK_VERSION}-bin"NODE1=192.168.80.11
NODE2=192.168.80.22
NODE3=192.168.80.33. /etc/os-releaseprint_status() {local message=$1local status=$2local GREEN='\033[0;32m'local RED='\033[0;31m'local YELLOW='\033[0;33m'local NC='\033[0m'local status_symbol=""case $status insuccess)status_symbol="[  OK  ]"color=$GREEN;;failure)status_symbol="[FAILED]"color=$RED;;warning)status_symbol="[WARN  ]"color=$YELLOW;;esacprintf "%-50s ${color}%s${NC}\n" "$message" "$status_symbol"
}detect_node_id() {local current_ip=$(hostname -I | awk '{print $1}')if [[ $current_ip == $NODE1 ]]; thenMYID=1elif [[ $current_ip == $NODE2 ]]; thenMYID=2elif [[ $current_ip == $NODE3 ]]; thenMYID=3elsewhile true; doread -p "输入节点编号 (1-3): " MYIDif [[ $MYID =~ ^[1-3]$ ]]; thenbreakelseprint_status "无效的节点编号,请输入1-3" warningfidonefiprint_status "节点ID: $MYID" success
}install_java() {print_status "安装Java环境..." successif [[ $ID == 'centos' || $ID == 'rocky' ]]; thenyum -y install java-1.8.0-openjdk-develelseapt updateapt install -y openjdk-8-jdkfiif java -version &>/dev/null; thenprint_status "Java安装成功" successjava -versionelseprint_status "Java安装失败" failureexit 1fi
}setup_zookeeper() {print_status "安装ZooKeeper..." successlocal install_dir="/usr/local/src"local zk_package="apache-zookeeper-${ZK_VERSION}-bin.tar.gz"local zk_home="/usr/local/zookeeper"mkdir -p $install_dirif [[ ! -f "$install_dir/$zk_package" ]]; thenprint_status "下载ZooKeeper安装包..." successwget -P $install_dir --no-check-certificate "$ZK_URL" || {print_status "下载失败: $ZK_URL" failureexit 1}fitar xf "$install_dir/$zk_package" -C /usr/local || {print_status "解压失败" failureexit 1}ln -sf "/usr/local/apache-zookeeper-${ZK_VERSION}-bin" "$zk_home"echo "export PATH=$zk_home/bin:\$PATH" > /etc/profile.d/zookeeper.shsource /etc/profile.d/zookeeper.shlocal data_dir="$zk_home/data"mkdir -p "$data_dir"echo "$MYID" > "$data_dir/myid"cat > "$zk_home/conf/zoo.cfg" <<EOF
tickTime=2000
initLimit=10
syncLimit=5
dataDir=$data_dir
clientPort=2181
maxClientCnxns=128
autopurge.snapRetainCount=3
autopurge.purgeInterval=24
server.1=$NODE1:2888:3888
server.2=$NODE2:2888:3888
server.3=$NODE3:2888:3888
EOFcat > /etc/systemd/system/zookeeper.service <<EOF
[Unit]
Description=Apache ZooKeeper Service
After=network.target[Service]
Type=forking
Environment="JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))"
ExecStart=$zk_home/bin/zkServer.sh start
ExecStop=$zk_home/bin/zkServer.sh stop
ExecReload=$zk_home/bin/zkServer.sh restart
User=root
Group=root
Restart=on-failure
RestartSec=10[Install]
WantedBy=multi-user.target
EOFsystemctl daemon-reloadsystemctl enable --now zookeeper.serviceif systemctl is-active --quiet zookeeper.service; thenprint_status "ZooKeeper 启动成功" successzkServer.sh statuselseprint_status "ZooKeeper 启动失败" failurejournalctl -u zookeeper.service -b --no-pagerexit 1fi
}main() {detect_node_idinstall_javasetup_zookeeperprint_status "ZooKeeper 节点 $MYID 安装完成" success
}main

依次执行脚本,并查看集群状态:

192.168.80.11:

192.168.80.22:

192.168.80.33:

测试故障转移:

停掉192.168.80.22 也就是leader:

查看节点状态,80.33成为leader

Zookeeper 客户端访问

1.连接集群

zkCli.sh -server 192.168.80.22:2181  #指定服务器连接
zkCli.sh  #默认连接本机

2.基础命令

命令作用示例
ls /查看根节点下所有节点ls /[zookeeper]
create创建节点(默认持久节点)create /appl "data"
get获取节点数据get /applhello,zookeeper
set修改节点数据set /appl "new_data"
delete删除无子节点的节点delete /appl
deleteall递归删除节点及其子节点deleteall /appl
stat查看节点元数据stat /zookeeper
version查看客户端版本version3.6.2...
TAB键列出所有支持命令输入后显示命令列表

3.节点类型特性

类型创建方式关键特性
持久节点create /path会话结束仍存在,支持创建子节点(需逐级创建)
临时节点create -e /path会话结束自动删除,不支持创建子节点

4.写入和读取

在test1下的config中写入或读取数据,所以Zookeeper中的文件可以理解为文件或文件夹,是通用的,既能存放数据又能当文件夹。

注意临时节点无法创建子目录:

http://www.xdnf.cn/news/868915.html

相关文章:

  • vue-16(Vuex 中的模块)
  • 智能推荐系统:协同过滤与深度学习结合
  • 从上下文学习和微调看语言模型的泛化:一项对照研究
  • 网络攻防技术十四:入侵检测与网络欺骗
  • `<CLS>` 向量是 `logits` 计算的“原材料”,`logits` 是基于 `<CLS>` 向量的下游预测结果
  • pikachu靶场通关笔记13 XSS关卡09-XSS之href输出
  • Spring 中注入 Bean 有几种方式?
  • 身体节奏失调现象探秘
  • Windows GDI 对象泄漏排查实战
  • Bootstrap 5学习教程,从入门到精通,Bootstrap 5 容器(Container)语法知识点及案例代码详解(4)
  • RAG-Gym:一个用于优化带过程监督的代理型RAG的统一框架
  • macOS 连接 Docker 运行 postgres
  • HarmonyOS 实战:给笔记应用加防截图水印
  • 【Kdump专题】kexec加载捕获内核和 makedumpfile保存Vmcore
  • GPUCUDA 发展编年史:从 3D 渲染到 AI 大模型时代(上)
  • LeetCode刷题---贪心算法---944
  • 《PyTorch:开启深度学习新世界的魔法之门》
  • 什么是分布式锁?几种分布式锁分别是怎么实现的?
  • Vue3+Vite中lodash-es安装与使用指南
  • 定制化5G专网服务,助力企业数字化转型
  • 华为OD最新机试真题-流水线-OD统一考试(B卷)
  • 在Mathematica中实现Newton-Raphson迭代的收敛时间算法
  • 【LLM大模型技术专题】「入门到精通系列教程」LangChain4j与Spring Boot集成开发实战指南
  • 学习笔记085——Spring Data JPA笔记
  • DeepSeek-R1-0528:学术写作的新纪元
  • CppCon 2015 学习:A C++14 Approach to Dates and Times
  • Vue 3 弹出式计算器组件(源码 + 教程)
  • SOC-ESP32S3部分:30-I2S音频-麦克风扬声器驱动
  • Go语言学习-->go的跨平台编译
  • 基于C++实现(WinForm) LAN 的即时通信软件