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

        // 注册到zk监听中
        zkClient.subscribeDataChanges("/zkTemp", iZkDataListener);

        //如果已经存在zkTemp节点,就等待
        if(zkClient.exists("/zkTemp")){
            countDownLatch=new CountDownLatch(1);
            System.err.println("订单号重复,请等待=================================");
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 删除事件通知
        zkClient.unsubscribeDataChanges("/zkTemp", iZkDataListener);

    }
}

分布式锁思路

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

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

原文地址:https://www.cnblogs.com/wnwn/p/11948984.html