Zookeeper分布式锁

Posted whtt

tags:

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

分布式锁解决思路

  分布式锁使用zk,在zk上创建一个临时节点(有效期)

  使用临时节点作为锁,因为节点不允许重复。

  如果能创建节点成功,生成订单号,如果创建节点失败,等待。

  临时节点zk关闭,释放锁,其他节点就可以重新生成订单号。

小案例

  依赖

    <dependency>
      <groupId>com.101tec</groupId>
      <artifactId>zkclient</artifactId>
      <version>0.10</version>
    </dependency>

 

  OrderNumber生成订单

 

public class OrderNumber {
    private static Integer number=0;
    //生成订单号
    public String getNumber(){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        ++number;
        return sdf.format(new Date())+"	"+number;
    }
}

 

  OrderService打印订单号

 

public class OrderService implements Runnable{
    private static OrderNumber orderNumber=new OrderNumber();
    private Lock lock=new ZkLockImpl();

    //生成订单
    public void getOrderNumber(){
        //获取锁
        lock.getLock();
        //生成订单号
        System.out.println("订单号生成成功:"+orderNumber.getNumber());
        //释放锁
        lock.unLock();
    }


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

    public static void main(String[] args) {
        for (int i=1;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 ZK_ADDRESS="0.0.0.0:2181";


    protected ZkClient zkClient=new ZkClient(ZK_ADDRESS);
    /**
     * 每一个进程在创建节点时,实际上就是获得了一把锁
     * 如果在获取锁是发现返回值为true,代表当前没有锁,我可以使用
     * 如果返回值为false,代表锁正在被占用,那么我只能等待
     *
     */
    @Override
    public void getLock() {
        //获取一把锁
        if (tryLock()){
            System.out.println("获取到锁资源");
        }else{
            //else代表锁正在被占用,请等待
            waitLock();
            //递归,再次获取锁
            getLock();
        }
    }

    @Override
    public void unLock() {
        //非等于空代表创建了订单号
        if (zkClient!=null){
            //关闭会话,删除节点
            zkClient.close();
        }
    }



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


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

 

  ZklockImpl实现

public class ZkLockImpl extends ZookeeperLock{
    private CountDownLatch countDownLatch = null;
    @Override
    public boolean tryLock() {
        try {
            //创建临时节点
            zkClient.createEphemeral("/zkTemp");
            return true;
        }catch (Exception ex){
            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();
                }
            }
        };
        //如果已经存在zkTemp节点,就等待
        if(zkClient.exists("/zkTemp")){
            countDownLatch=new CountDownLatch(1);
            System.out.println("订单号重复,请等待=================================");
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

 

 

 

 

 

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

Zookeeper分布式锁

zooKeeper实现分布式锁

ZooKeeper分布式锁简单实践

基于zookeeper的分布式锁实现

zookeeper怎么实现分布式锁

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