结构

Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务。

ZooKeeper 的树形结构不仅是数据组织形式,更是其实现分布式协调功能的基础。服务注册、配置管理、Leader 选举和分布式锁等功能,本质上都是通过树节点的创建、删除、监听和顺序管理来实现的。

节点

类型 是否自动删除 是否带编号
持久节点(Persistent)
临时节点(Ephemeral)
持久顺序节点(Persistent Sequential)
临时顺序节点(Ephemeral Sequential)

是否永久就是客户端断开是否自动删除

部署

单机

Apache ZooKeeper 是:一个Java服务程序

解压后目录结构是bin/ conf/ logs/ lib/

创建conf/zoo.cfg配置文件

tickTime=2000#心跳检测、Session 超时、Leader 选举节奏、Follower 同步节奏(毫秒)
dataDir=/tmp/zookeeper#ZooKeeper 持久化数据存放位置
clientPort=2181#客户端连接 ZooKeeper 的入口端口

dataDir=/data/zookeeper#生产环境改成这个,因为Linux可能自动清理/tmp

#或者详细点区分
ataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/log

initLimit=10 #Follower 初始化同步 Leader 的最大时间
syncLimit=5 #Follower 与 Leader 心跳同步的最大延迟容忍
#initLimit 和 syncLimit 只针对 ZooKeeper 自己的集群(ZK集群内部)

bin/zkServer.sh start 启动

bin/zkServer.sh status 查看状态

bin/zkServer.sh stop 停止

集群

必须“多数派存活”才算集群可用(Quorum机制)

#每台机器都一样:
tickTime=2000
dataDir=/data/zookeeper
clientPort=2181#客户端连接

server.1=192.168.1.10:2888:3888
server.2=192.168.1.11:2888:3888
server.3=192.168.1.12:2888:3888

#server.x表示节点编号
#server.编号=IP:Follower通信端口:选举端口

#每台机器必须有 myid,myid不是目录,是文件,里面的内容就是id值
在 dataDir 目录下:/data/zookeeper/myid

选Leader

ZooKeeper 集群启动后通过 ZAB 协议进行 Leader 选举,优先比较 epoch,其次比较 zxid(事务ID),最后比较 myid,最终由拥有最新数据的多数节点共同选出 Leader,其他节点作为 Follower 同步数据。

zxid = ZooKeeper Transaction ID(事务ID)
数据“写操作”的顺序编号
每一次写操作都会生成一个 zxid
ZooKeeper 自动维护

epoch(任期号)
由 ZooKeeper 集群自动生成
保证: 新Leader的数据一定比旧Leader更新

ZAB

ZAB 协议(ZooKeeper Atomic Broadcast)

保证 ZooKeeper 集群数据一致性的广播协议

ZAB 协议是 ZooKeeper 的一致性协议,分为崩溃恢复和原子广播两个阶段,通过 Leader 选举、事务 zxid 顺序编号以及多数派确认机制,保证分布式环境下的数据强一致性。

目标 说明
1️⃣ 一致性 所有节点数据一致
2️⃣ 顺序性 写操作有全局顺序
3️⃣ 高可用 Leader挂了能恢复

服务注册

#springcloud
spring:
  application:
    name: user-service
  cloud:
    zookeeper:
      connect-string: 127.0.0.1:2181
      #如果是集群
      connect-string: 192.168.1.10:2181,192.168.1.11:2181,192.168.1.12:2181
      #也可以设置心跳和session超时
      session-timeout: 30000
      connection-timeout: 10000

ZooKeeper 集群中的每个节点都会同步保存完整的注册数据,
包括服务节点、地址和状态信息;
写请求统一由 Leader 处理,再同步到 Follower,以保证强一致性。

所以就是,springcloud部署到zookeeper集群,每个zookeeper都有一样的springcloud信息。

springcloud集群在zookeeper里没有主从

Spring Cloud Zookeeper默认使用临时节点
Spring Cloud Zookeeper实现了默认注册路径
Spring Cloud Zookeeper默认设置了心跳和session超时
Spring Cloud Zookeeper 已经帮你封装好了Watcher

Curator

Apache Curator 是一个“专门用来简化 ZooKeeper 使用的客户端框架”。

服务注册

//创建客户端
CuratorFramework client = CuratorFrameworkFactory.builder()
        .connectString("127.0.0.1:2181")
        .sessionTimeoutMs(30000)
        .connectionTimeoutMs(30000)
        .retryPolicy(new ExponentialBackoffRetry(1000, 3))
        .build();

client.start();
//创建节点
client.create()
      .creatingParentsIfNeeded()
      .forPath("/services/user-service", "online".getBytes());

Leader选举

Leader 选举选的不是普通业务服务
也不是 ZooKeeper 本身
而是“某一类需要主节点角色的服务实例”

计数器

Curator 提供 DistributedAtomicInteger 和 SharedCount 两种分布式计数器实现,本质基于 ZooKeeper 的 Znode + version CAS 机制,通过重试保证并发安全,从而避免手动实现读改写冲突问题。

Barrier

Curator 的 Barrier(DistributedBarrier)基于 ZooKeeper 节点状态实现分布式同步控制,所有参与节点在 waitOnBarrier 阻塞等待,当控制方调用 removeBarrier 删除屏障节点后,所有节点同时被唤醒继续执行,实现分布式“统一放行”机制。

分布式锁

InterProcessMutex lock = new InterProcessMutex(client, "/lock");

lock.acquire();   // 加锁
lock.release();   // 解锁

配置中心

NodeCache cache = new NodeCache(client, "/config/db.url");

cache.getListenable().addListener(() -> {
    String newValue = new String(cache.getCurrentData().getData());
    System.out.println("配置变更:" + newValue);
});

cache.start();

强一致性

所有“不能出错的协调类功能”都依赖强一致:
1️⃣ 分布式锁
2️⃣ Leader 选举
3️⃣ 配置中心
4️⃣ 注册/发现(服务目录一致性)

强一致说的“数据”,本质就是 ZooKeeper 内部 Znode 上的数据 + 节点状态变化

ZooKeeper 的强一致性保证的是注册中心内部数据和服务列表的全局一致性,但不保证客户端请求绝对不会命中失效实例;请求是否打到坏节点,取决于客户端缓存、负载均衡和网络延迟,只是 ZooKeeper 通过快速删除节点和 Watcher 机制将这一不一致窗口压缩到极短。

更多推荐