zoukankan      html  css  js  c++  java
  • 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();
                }
            }
    
        }
    }
  • 相关阅读:
    Oracle的导入导出
    Android利用数据库传送数据
    Android相对布局实例
    git拉取github项目
    kafka支持认证SASL_PLAINTEXT
    fluentd插件开发
    解决go依赖包安装问题
    ES/Kibana支持search-guard认证
    logkit docker运行和代码下载
    CentOS安装指定git版本
  • 原文地址:https://www.cnblogs.com/whtt/p/11951640.html
Copyright © 2011-2022 走看看