分布式锁简单 概述和实例(zookeeper)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WO8451401/article/details/79923663
 
 

首选 安装zookeeper,解压  启动, 看是否能正常启动, 其中配置文件中 需要copy zoo_sample 一份 命名成 zoo.cfg


然后启动起来,  其次是修改你的ip和端口

然后小实现

private ZooKeeper zk;
private String root = "/locks";//根
private String lockName;
private String waitNode;//等待前一个锁
private String myZnode;//当前锁
private CountDownLatch latch;//计数器
private CountDownLatch connectedSignal=new CountDownLatch(1);
private int sessionTimeout = 30000;


/**
 * 创建分布式锁,使用前请确认config配置的zookeeper服务可用
 * @param config 192.168.1.90:2181
 * @param lockName 竞争资源标志,lockName中不能包含单词_lock_
 */
public DistributedLock(String config, String lockName){
    this.lockName = lockName;
    // 创建一个与服务器的连接
    try {
        zk = new ZooKeeper(config, sessionTimeout, this);
        connectedSignal.await();
        Stat stat = zk.exists(root, false);//此去不执行 Watcher
        if(stat == null){
            // 创建根节点
            zk.create(root, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
    } catch (IOException e) {
        System.out.println(e);
    } catch (KeeperException e) {
        System.out.println(e);
    } catch (InterruptedException e) {
        System.out.println(e);
    }
}

设置监听器

/**
 * zookeeper节点监听器
 */
public void process(WatchedEvent event){
    //建立连接
    if(event.getState() == Event.KeeperState.SyncConnected){
        connectedSignal.countDown();
        return ;
    }
    if(this.latch !=null ){
        this.latch.countDown();
    }


    return ;
}

默认调用锁方法

public void lock() {
    try {
        if(this.tryLock()){
            System.out.println("Thread " + Thread.currentThread().getId() + " " +myZnode + " get lock true");
            return;
        }
        else{
            waitForLock(waitNode, sessionTimeout);//等待锁
        }
    } catch (KeeperException e) {
        System.out.println(e);
    } catch (InterruptedException e) {
        System.out.println(e);
    }
}

public boolean tryLock() {
    try {
        String splitStr = "_lock_";
        if(lockName.contains(splitStr))
            System.out.println("lockName can not contains \\u000B");
        //创建临时子节点
        myZnode = zk.create(root + "/" + lockName + splitStr, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(myZnode + " is created ");
        //取出所有子节点
        List<String> subNodes = zk.getChildren(root, false);
        //取出所有lockName的锁
        List<String> lockObjNodes = new ArrayList<String>();
        for (String node : subNodes) {
            String _node = node.split(splitStr)[0];
            if(_node.equals(lockName)){
                lockObjNodes.add(node);
            }
        }
        Collections.sort(lockObjNodes);

        if(myZnode.equals(root+"/"+lockObjNodes.get(0))){
            //如果是最小的节点,则表示取得锁
            System.out.println(myZnode + "==" + lockObjNodes.get(0));
            return true;
        }
        //如果不是最小的节点,找到比自己小1的节点
        String subMyZnode = myZnode.substring(myZnode.lastIndexOf("/") + 1);
        waitNode = lockObjNodes.get(Collections.binarySearch(lockObjNodes, subMyZnode) - 1);//找到前一个子节点
    } catch (KeeperException e) {
        System.out.println(e);
    } catch (InterruptedException e) {
        System.out.println(e);
    }
    return false;
}
public boolean tryLock(long time, TimeUnit unit) {
    try {
        if(this.tryLock()){
            return true;
        }
        return waitForLock(waitNode,time);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

判断节点数  是否是最小的

private boolean waitForLock(String lower, long waitTime) throws InterruptedException, KeeperException {
    Stat stat = zk.exists(root + "/" + lower,true);//同时注册监听。
    //判断比自己小一个数的节点是否存在,如果不存在则无需等待锁,同时注册监听
    if(stat != null){
        System.out.println("Thread " + Thread.currentThread().getId() + " waiting for " + root + "/" + lower);
        this.latch = new CountDownLatch(1);
        this.latch.await(waitTime, TimeUnit.MILLISECONDS);//等待,这里应该一直等待其他线程释放锁
        this.latch = null;
    }
    return true;
}
public void unlock() {
    try {
        System.out.println("unlock " + myZnode);
        zk.delete(myZnode,-1);
        myZnode = null;
        zk.close();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (KeeperException e) {
        e.printStackTrace();
    }
}


最后测试

public static void main(String[] args){
    DistributedLock lock   = new DistributedLock("192.168.1.90:2181","lock");
    lock.lock();
    //共享资源
    if(lock != null)
        lock.unlock();

}








猜你喜欢

转载自blog.csdn.net/WO8451401/article/details/79923663