• 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关闭,释放锁,其他节点就可以重新生成订单号。

  • 相关阅读:
    uniApp 滑动手势事件判定 支持NVUE
    按照指定数字 分割数组
    我引用中没有Spire.Pdf,但是发现无法解析的“Spire.Pdf”的不同版本之间存在冲突
    RedisUtil工具类
    Hutool操作excel
    Java 值传递与引用传递
    修改homestead中PHP cli版本
    VS2022 vs2022 servicehub.roslyncodeanalysisservice.exe 占用内存过高
    操作系统
    Spring Security BCryptPasswordEncoder 每次Hash出来的值都不同?
  • 原文地址:https://www.cnblogs.com/wnwn/p/11948984.html
Copyright © 2020-2023  润新知