分布式锁方案三 Zookeeper 实现机制分析

ZooKeeper 分布式锁机制分析

ZooKeeper 是一个开源的分布式协调服务,其强一致性(CP)和节点有序性,使它非常适合实现 强一致性分布式锁,尤其在金融、电商、调度系统等高一致性要求场景中广泛使用。


一、核心原理:临时顺序节点 + 监听机制(Watch)

基本流程图解(核心步骤):

  1. 客户端在指定路径下创建临时顺序节点

    /lock/resource/lock-000000001
    /lock/resource/lock-000000002
    ...
    
  2. 所有客户端获取该路径下的所有子节点,判断自己是不是最小编号

    • 是:获取锁;
    • 否:监听比自己小的前一个节点是否删除
  3. 前一个节点删除后(持锁客户端释放锁)→ Watch 被触发 → 当前节点获取锁。

  4. 客户端断线或宕机 → 临时节点自动删除 → 锁自动释放。


二、代码实现概念(伪代码)

// 1. 创建临时顺序节点
String path = zkClient.create("/lock/order-", null, 
	EPHEMERAL_SEQUENTIAL);

// 2. 获取所有子节点并排序
List<String> children = zkClient.getChildren("/lock");
Collections.sort(children);

// 3. 判断自己是否是最小节点
if (path.endsWith(children.get(0))) {
    // 成功获得锁
} else {
    // 监听前一个节点(非最小)
    String prevNode = findPreviousNode(children, path);
    zkClient.exists("/lock/" + prevNode, watcher);
}

三、ZooKeeper 分布式锁具备的能力

能力 说明
强一致性 基于 ZAB 协议,所有节点对数据的视图一致
自动释放 客户端断连,临时节点自动清除,锁自动释放
公平性 顺序节点 + 监听机制 → 谁先排队,谁先拿锁
高可用 多个 ZooKeeper 节点组成集群,防单点故障

四、优缺点对比

优点 说明
强一致性保障 拿到锁的一定是唯一“最小编号”的客户端
天然公平锁 谁先来谁排前面,避免插队
锁丢失概率极低 临时节点 + Watch 避免误删
缺点 说明
性能不如 Redis ZK 每次加锁需要读取、排序、监听 → 更慢
代码逻辑较复杂 实现 Watch + 顺序逻辑比 Redisson 更繁琐
需维护 ZK 集群 运维要求高,依赖重,不适合轻量场景

五、适合使用 ZK 锁的业务场景

场景 原因
金融核心交易操作 严格强一致、不可同时执行
分布式定时任务调度 防止多个节点重复调度任务
全局唯一资源分配 比如流水号生成、状态机转换
多节点共享状态转移控制 如订单状态变更流程控制

六、实际项目可使用的组件封装(推荐)

  • Apache Curator:Netflix 出品的 ZooKeeper 客户端封装库,提供简洁的 InterProcessMutex
    InterProcessMutex lock = new InterProcessMutex(client, 
    	"/lock/order");
    	
    if (lock.acquire(3, TimeUnit.SECONDS)) {
        try {
            // 执行业务逻辑
        } finally {
            lock.release();
        }
    }
    
  • 支持可重入、超时等待、异常自动释放;
  • 自动处理 Watcher 注册/取消、节点创建/删除逻辑。

七、项目中使用 ZK 锁的答题模板

在我们早期的分布式调度系统中,为保障任务唯一执行,我们采用了 ZooKeeper 实现分布式锁。

  • 所有执行节点通过在 /lock/job 路径下创建临时顺序节点竞争锁;
  • 成功获得最小节点者执行任务,失败者监听前一个节点;
  • 使用 Apache Curator 封装,确保在节点宕机、网络波动时锁能自动释放,避免了传统 Redis 锁在主从切换时可能的锁丢失问题;

这样,我们实现了任务调度系统的高可靠锁控制,确保任何时刻都只有一个节点触发关键任务。

你可能感兴趣的:(Java面试专项,分布式,zookeeper,面试,分布式锁,并发,实现机制)