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 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));
}
}

你可能感兴趣的:(zookeeper实现分布式锁,zookeeper)