zookeeper分布式锁

Posted wnwn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了zookeeper分布式锁相关的知识,希望对你有一定的参考价值。

分布式锁

  技术图片

流程

  • 查看目标Node是否已经创建,已经创建,那么等待锁。
  • 如果未创建,创建一个临时节点zkTemp,表示已经占有锁。
  • 如果创建失败,那么证明锁已经被其他线程占有了,那么同样等待锁。
  • 当释放锁,节点被删除,唤醒之前等待锁的线程去争抢锁。

分布式案例

  OrderNumber生成订单号类:

/*生成订单号*/
public class OrderNumber {

    private static int number=0;

    //生成订单号
    public String getOrderNumber(){
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        ++number;
        return simpleDateFormat.format(new Date())+"	"+number;
    }

}

  OrderService订单业务逻辑类:

/*订单业务逻辑*/
public class OrderService implements Runnable {
    private static OrderNumber orderNumber=new OrderNumber();
    public Lock lock=new ZookeeperImpl();

    //生成订单
    public void getnumber(){
        /*synchronized (orderNumber){
            System.out.println("获取的订单编号为:"+orderNumber.getOrderNumber());
        }*/

        lock.getLock();     //获取锁
        System.out.println("获取的订单编号为:"+orderNumber.getOrderNumber());
        lock.unLock();      //释放锁
    }


    @Override
    public void run() {
        getnumber();
    }

    public static void main(String[] args) {
        for (int i=0;i<100;i++){
            new Thread(new OrderService()).start();
        }
    }

}

  Lock接口类:

public interface Lock {

    //获取锁
    public void getLock();

    //释放锁
    public void unLock();
}

  ZookeeperLock实现类:

public abstract class ZookeeperLock implements Lock {
    //连接地址
    private static final String CONNECT_ADDDR="0.0.0.0:2181";

    protected ZkClient zkClient=new ZkClient(CONNECT_ADDDR);


    //获取锁
    @Override
    public void getLock() {
        if (tryLock()){
            System.out.println("获取到锁资源");
        }else{
            //当返回值为false的时候,代表锁已经被占用,需等待锁
            waitLock();
            //等待之后需再次获取锁
            getLock();
        }


    }

    //释放锁
    @Override
    public void unLock() {
        if (zkClient!=null){
            zkClient.close();
        }
    }

    //获取锁资源
    public abstract boolean tryLock();

    //等待
    public abstract void waitLock();
}

  ZookeeperImpl继承类:

/*真正获取锁和释放锁*/
public class ZookeeperImpl extends ZookeeperLock {

    //信号量
    private CountDownLatch countDownLatch=null;

    //获取锁资源
    @Override
    public boolean tryLock() {
        try {
            zkClient.createEphemeral("/zkTemp");
            return true;
        }catch (Exception e){
            return false;
        }
    }

    //等待
    @Override
    public void waitLock() {
        IZkDataListener iZkDataListener=new IZkDataListener() {
            @Override
            public void handleDataChange(String s, Object o) throws Exception {

            }

            @Override
            public void handleDataDeleted(String s) throws Exception {
                if (countDownLatch!=null){
                 //释放信号量
                    countDownLatch.countDown();
                }
            }
        };
        //如果节点已经存在  就等待
        if (zkClient.exists("/zkTemp")){
            countDownLatch=new CountDownLatch(1);
            System.out.println("锁已经被占用  需要等待============================");
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

分布式锁思路

  分布式锁使用zk,在zk上创建一个临时节点(有效期)  ,使用临时节点作为锁,因为节点不允许重复。

  如果能创建节点成功,生成订单号,如果创建节点失败,等待。临时节点zk关闭,释放锁,其他节点就可以重新生成订单号。

 

以上是关于zookeeper分布式锁的主要内容,如果未能解决你的问题,请参考以下文章

Zookeeper分布式锁

zooKeeper实现分布式锁

ZooKeeper分布式锁简单实践

基于zookeeper的分布式锁实现

zookeeper怎么实现分布式锁

基于Zookeeper实现的分布式互斥锁 - InterProcessMutex