zookeeper实现分布式锁

本文详细介绍了如何使用Zookeeper实现分布式锁,包括其实现原理、Java代码实现过程。通过创建临时顺序节点,利用Zookeeper的特性确保分布式环境中资源的独占访问。

1、实现原理

分布式系统中分布式锁是经常是经常用到的,比如买票程序,当一个进程在使用公共资源时,其他进程应该处于等待状态,直到当前资源释放后才能获取锁。

zookeeper实现分布式锁的原理如下:

1、创建当前结点
2、获取当前节点的所有兄弟节点
3、判断当节点是否为兄弟节点的第一个第一个节点
3.1、是,获取锁
3.2、不是,获取当前结点的前一个节点,等到前一个节点释放锁后,获取锁

2、java代码实现

package com.cn.willy;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class MyLock {

private static final String URL="192.168.43.134:2181";

private static final int TIME_OUT=5000;

private CountDownLatch latch = new CountDownLatch(1);

private ZooKeeper zooKeeper = null;

private String localPath = "";

private boolean setLocalPath = true;

/**
 * 使用构造方法实例化zk实例
 */
public MyLock(){
    try{
        zooKeeper = new ZooKeeper(URL, TIME_OUT, new Watcher() {
            public void process(WatchedEvent event) {
                if (event.getType() == Event.EventType.None){
                    if (event.getState() == Event.KeeperState.SyncConnected){
                        latch.countDown();
                        System.out.println("connection zookeeper");
                    }
                }
            }
        });
        latch.await();
    }catch (Exception e){
        e.printStackTrace();
    }
}

/**
 * 递归创建单节点
 * @param path
 * @return
 */
public String createNode(String path){

    String tempPath = "";
    try{
        if (setLocalPath){
            localPath = path;
            setLocalPath = false;
        }
        Stat stat = zooKeeper.exists(path,false);
        if(stat == null){
            if(path.split("/").length > 2){
                createNode(path.substring(0,path.lastIndexOf("/")));
            }
            if (localPath.equals(path)){
                tempPath = zooKeeper.create(path,new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
                localPath = tempPath;
            }else{
                tempPath = zooKeeper.create(path,new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
        }
    }catch (Exception e){
        e.printStackTrace();
    }
    return tempPath;
}

/**
 * 节点变更监听
 */
Watcher watcher = new Watcher() {
    public void process(WatchedEvent event) {
        if (event.getType() == Event.EventType.NodeDeleted){
            //唤醒阻塞节点
            synchronized (this){
                this.notifyAll();
            }

        }
    }
};

/**
 * 获取锁
 */
public void attempLock(){
    try{
        //1、获取当前结点的所有节点
        List<String> list = zooKeeper.getChildren(localPath.substring(0,localPath.lastIndexOf("/")),false);
        //2、对几点排序
        Collections.sort(list);
        //3、判断当前节点是否为第一个节点
        int index = list.indexOf(localPath);
        //3.1、是第一个节点直接返回
        if(index == 0){
            return;
        }else{
            //3.2、不是第一个节点,则获取当前结点的前一个节点
          String upPath = list.get(index+1);
            Stat stat = zooKeeper.exists(upPath,watcher);
            //此时前一个节点已经被处理,表示当前节点可以获取资源
            if (stat == null){
                attempLock();
            }else{
                //阻塞当前结点、等待前一个节点完成
                synchronized (watcher){
                    watcher.wait();
                }
                attempLock();
            }
        }
    }catch (Exception e){
        e.printStackTrace();
    }
}

/**
 * 释放当前结点
 */
public void releaseLock(){
    try{
        zooKeeper.delete(localPath,-1);
        zooKeeper.close();
    }catch (Exception e){
        e.printStackTrace();
    }

}

public static void main(String[] args) {
    String path = "/fsm/dep/purch/lock/lock_";
    MyLock lock = new MyLock();
    System.out.println(lock.createNode(path));
}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值