ZooKeeper 原理与实战(Java 开发者视角)

一、Zookeeper 是什么?

Zookeeper是一个分布式协调服务,主要解决分布式系统中的一致性问题。它提供了一套类似文件系统的树形结构,节点称为 ZNode,用于存储少量数据和元信息。

Zookeeper 保证了:

  1. 强一致性:所有客户端读取到的数据都是一致的。
  2. 顺序性:每个更新请求会按顺序执行。
  3. 高可用性:通过集群(一般是奇数台,3/5 台)保证服务可用。

二、Zookeeper 的核心原理

1. 数据模型

Zookeeper 的数据结构类似于树:

/app
   ├── config
   ├── workers
   └── leader

每个节点(ZNode)都可以存储数据,并且支持 临时节点顺序节点

  • 持久节点:不会因为客户端断开而消失。
  • 临时节点:客户端断开后自动删除。
  • 顺序节点:自动带上递增编号。

2. Watcher 机制

Zookeeper 支持 数据变更监听。客户端可以对某个节点注册 Watcher,一旦节点发生变化(新增/删除/修改),客户端会收到通知。

3. Leader 选举

Zookeeper 采用 ZAB 协议(Zookeeper Atomic Broadcast)来保证一致性。
核心流程:

  1. 集群启动时选举一个 Leader。
  2. Leader 负责写请求,Follower 负责读请求。
  3. 写请求必须过半节点确认(多数派机制)。

4. 会话机制

客户端与服务端之间维持一个Session,通过心跳保持连接。临时节点的生命周期与 Session 绑定。

三、使用场景

1. 分布式配置中心

应用把配置存放在 Zookeeper 节点中,客户端通过 Watcher 机制实时感知配置变化。

2. 服务注册与发现

服务启动时向 Zookeeper 注册节点(临时节点),消费者从 Zookeeper 获取服务地址,实现服务发现。

3. 分布式锁

基于 临时顺序节点,实现分布式锁:

  • 多个客户端在某个路径下创建顺序节点。
  • 节点编号最小的客户端获得锁。
  • 其他客户端监听前一个节点,一旦释放则竞争锁。

4. Leader 选举

分布式系统中需要一个 Master 节点时,可以基于临时顺序节点实现 Leader 选举。

四、使用案例(Java 实战)

1. Maven 依赖

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.8.0</version>
</dependency>

2. Java 代码示例

(1)连接 Zookeeper

import org.apache.zookeeper.ZooKeeper;

public class ZKConnect {
    public static void main(String[] args) throws Exception {
        ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, event -> {
            System.out.println("Watcher: " + event);
        });
        System.out.println("连接成功: " + zk.getState());
    }
}

(2)创建节点

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;

public class ZKCreateNode {
    public static void main(String[] args) throws Exception {
        ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
        String path = zk.create("/app/config", "v1".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("创建节点: " + path);
    }
}

(3)分布式锁实现

import org.apache.zookeeper.*;

public class DistributedLock {
    private static final String LOCK_PATH = "/lock";

    public void acquireLock() throws Exception {
        ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
        String nodePath = zk.create(LOCK_PATH + "/lock_", new byte[0],
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

        // 获取子节点并判断自己是否是最小节点
        var children = zk.getChildren(LOCK_PATH, false);
        children.sort(String::compareTo);
        if (nodePath.endsWith(children.get(0))) {
            System.out.println("获取到锁: " + nodePath);
        } else {
            System.out.println("等待锁...");
        }
    }
}

五、总结

  • Zookeeper = 分布式协调服务,核心是 一致性 + Watcher +
    临时/顺序节点
  • 常见用途:配置中心、注册中心、分布式锁、Leader 选举
  • 对 Java 开发者而言,Zookeeper 就是分布式系统的"协调管家"。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容