Zookeeper实战分布锁

一,分布式锁实现技术

基于数据实现分布式锁

         性能较差,容易出现单点故障

        锁没有失效事件,容易死锁。

        非阻塞式

        不可重入

基于缓存实现分布式锁

          锁没有失效事件,容易死锁

         非阻塞式

         不可重入

基于Zookeeper实现分布式锁

          实现相对简单

          可靠性高

          性能较好

二,Zookeeper应用场景

       数据发布订阅

       负载均衡

       命名服务

       分布式协调

       集群管理

       配置管理

       分布式队列

       分布式

三,Zookeeper实战分布式锁

   

         

        

            

/**
 * 获取锁和释放锁真正实现的类
 */
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();
            }

        }

    }

}

  

public abstract class ZookeeperLock implements Lock{
    /**
     * 创建zkClient连接对象
     */
    private static final String ZK_ADDRESS="0.0.0.0:2181";

    protected ZkClient zkClient=new ZkClient(ZK_ADDRESS);


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

    }


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


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


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

 

三,分布式锁解决思路

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

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

原文地址:https://www.cnblogs.com/liuying23/p/11955712.html