zookeeper基础操作--zookeeper的下载、安装,以及基本命令和简单实例操作
一、Zookeeper 简介、应用场景与常用功能
1. Zookeeper 简介
Zookeeper 是一个分布式协调服务,由 Apache 开源,主要用于解决分布式系统中的一致性问题。
核心特点:
- 采用树形文件系统结构(ZNode)存储数据
- 提供高可用性和顺序一致性
- 基于 ZAB 协议(Zookeeper Atomic Broadcast)实现数据同步
2. 应用场景
2.1 典型场景
- 分布式锁:实现互斥访问共享资源
- 配置中心:集中管理集群配置信息
- 服务注册与发现(如 Dubbo)
- 集群选主(Leader Election)
- 分布式队列
2.2 行业案例
- Hadoop(YARN 资源管理)
- Kafka(Broker 元数据管理)
- HBase(RegionServer 状态跟踪)
3. 常用功能
3.1 基础功能
3.2 高级特性
// Java API 示例:创建节点ZooKeeper zk = new ZooKeeper(\"localhost:2181\", 3000, null);zk.create(\"/test_node\", \"data\".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
注意事项:
- 节点数据大小限制为 1MB
- 默认端口 2181(客户端通信)、2888(Leader 选举)、3888(集群通信)
- 推荐奇数台服务器组成集群(3/5/7台)
二、Zookeeper下载和安装
1. 下载Zookeeper
访问Apache Zookeeper官网下载页面:
https://zookeeper.apache.org/releases.html
选择稳定版本(例如3.7.1)下载:
https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.7.2/apache-zookeeper-3.7.2-bin.tar.gz
wget https://downloads.apache.org/zookeeper/zookeeper-3.7.1/apache-zookeeper-3.7.1-bin.tar.gz
2. 安装步骤
2.1 解压安装包
tar -zxvf apache-zookeeper-3.7.1-bin.tar.gzcd apache-zookeeper-3.7.1-bin
2.2 配置Zookeeper
复制示例配置文件并修改:
cp conf/zoo_sample.cfg conf/zoo.cfg
编辑conf/zoo.cfg
(主要配置项):
dataDir=/tmp/zookeeperclientPort=2181
2.3 启动服务
bin/zkServer.sh start
2.4 验证运行状态
bin/zkServer.sh status
3. 常用命令
zkServer.sh start
zkServer.sh stop
zkCli.sh -server
注意:生产环境建议配置集群模式(至少3个节点)并设置
dataLogDir
。
三、Zookeeper常用功能和原理
1、常用功能
1.1分布式协调服务
- 提供分布式环境下的节点协调、状态同步等功能
1.2配置管理
- 集中式配置存储和动态更新
- 配置变更通知机制
1.3命名服务
- 类似DNS的命名系统
- 通过路径标识资源
1.4集群管理
- 节点注册与监控
- 领导者选举(Leader Election)
1.5分布式锁
- 实现排他锁、共享锁等同步机制
1.6队列管理
- 实现FIFO队列、屏障等数据结构
2、核心原理
2.1数据模型
- 采用ZNode树形结构(类似文件系统)
- 每个ZNode可存储少量数据(默认≤1MB)
2.2Watcher机制
- 一次性触发的事件通知
- 客户端可监听ZNode变化
2.3ZAB协议
- ZooKeeper Atomic Broadcast协议
- 保证分布式事务的顺序一致性
2.4会话(Session)
- 客户端与服务端保持TCP长连接
- 会话超时机制
2.5集群角色
- Leader: 处理所有写请求
- Follower: 处理读请求并参与选举
- Observer: 仅处理读请求(不参与选举)
2.6数据一致性
- 顺序一致性(Sequential Consistency)
- 原子性(Atomicity)
- 单一系统映像(Single System Image)
典型应用场景
- 分布式锁服务
- 分布式配置中心
- 服务注册与发现
- 分布式队列
- 集群选主
四、简单实例
ZooKeeper 是一个分布式协调服务,常用于管理分布式系统中的配置信息、命名服务、分布式同步等。下面介绍其基本使用方法:
1. 安装与启动
单机模式
1.1下载并解压
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.8.2/apache-zookeeper-3.8.2-bin.tar.gztar -zxvf apache-zookeeper-3.8.2-bin.tar.gzcd apache-zookeeper-3.8.2-bin
1.2配置
创建配置文件 conf/zoo.cfg
:
tickTime=2000dataDir=/path/to/dataclientPort=2181
1.3启动服务
bin/zkServer.sh start
2. 基本命令行操作
通过客户端连接 ZooKeeper:
bin/zkCli.sh -server localhost:2181
常用命令:
# 创建节点(-e 临时节点,-s 有序节点)create /my-node \"hello\"create -e /my-ephemeral \"temp\"# 查看节点ls /get /my-node# 更新节点set /my-node \"world\"# 删除节点delete /my-node
3. Java API 使用
依赖
Maven 项目添加依赖:
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.8.2</version></dependency>
示例代码
import org.apache.zookeeper.*;import java.io.IOException;public class ZooKeeperExample { private static final String CONNECT_STRING = \"localhost:2181\"; private static final int SESSION_TIMEOUT = 3000; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { // 连接 ZooKeeper ZooKeeper zk = new ZooKeeper(CONNECT_STRING, SESSION_TIMEOUT, null); // 创建持久节点 String path = zk.create(\"/my-java-node\", \"data\".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println(\"Created node: \" + path); // 获取节点数据 byte[] data = zk.getData(\"/my-java-node\", false, null); System.out.println(\"Data: \" + new String(data)); // 更新节点 zk.setData(\"/my-java-node\", \"new-data\".getBytes(), -1); // 删除节点 zk.delete(\"/my-java-node\", -1); // 关闭连接 zk.close(); }}
4. 分布式锁示例
利用 ZooKeeper 的有序节点和 watcher 机制实现分布式锁:
import org.apache.zookeeper.*;import java.io.IOException;import java.util.Collections;import java.util.List;public class DistributedLock { private final ZooKeeper zk; private final String lockPath; private String currentNode; public DistributedLock(String connectString, String lockPath) throws IOException { this.zk = new ZooKeeper(connectString, 3000, null); this.lockPath = lockPath; ensurePathExists(lockPath); } public void acquire() throws KeeperException, InterruptedException { // 创建临时有序节点 currentNode = zk.create(lockPath + \"/lock-\", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); // 获取所有子节点并排序 List<String> children = zk.getChildren(lockPath, false); Collections.sort(children); // 如果当前节点是第一个,则获取锁 if (currentNode.endsWith(children.get(0))) { return; } // 否则,监听前一个节点 String prevNode = children.get(children.indexOf(currentNode.substring(lockPath.length() + 1)) - 1); synchronized (this) { zk.exists(lockPath + \"/\" + prevNode, new Watcher() { @Override public void process(WatchedEvent event) { synchronized (DistributedLock.this) { DistributedLock.this.notify(); } } }); this.wait(); } } public void release() throws KeeperException, InterruptedException { if (currentNode != null) { zk.delete(currentNode, -1); currentNode = null; } } private void ensurePathExists(String path) { try { if (zk.exists(path, false) == null) { zk.create(path, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (Exception e) { e.printStackTrace(); } }}
5. 集群配置
在多台机器上部署 ZooKeeper 集群,修改 zoo.cfg
:
tickTime=2000dataDir=/path/to/dataclientPort=2181initLimit=5syncLimit=2# 集群节点配置server.1=host1:2888:3888server.2=host2:2888:3888server.3=host3:2888:3888
在每台机器的 dataDir
目录下创建 myid
文件,内容为对应服务器的 ID(如 1
、2
、3
)。
注意事项
-
节点类型
:
- 持久节点:创建后一直存在,除非手动删除。
- 临时节点:会话结束后自动删除。
- 有序节点:节点名后会自动添加递增编号。
-
Watcher 机制:监听节点变化,触发一次后失效,需重新注册。
-
生产环境建议
:
- 集群规模推荐奇数台(3、5、7 台)。
- 避免频繁创建 / 删除节点,影响性能。
- 监控
zkServer.sh status
查看集群状态。
配置\"log4j\"
# 设置根日志级别为INFO,输出到控制台log4j.rootLogger=INFO, stdout# 配置控制台输出log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target=System.outlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
查看集群状态。
配置\"log4j\"
[外链图片转存中…(img-JG1ZxTmq-1751986721579)]
# 设置根日志级别为INFO,输出到控制台log4j.rootLogger=INFO, stdout# 配置控制台输出log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target=System.outlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n