zoukankan      html  css  js  c++  java
  • 使用Zookeeper实现分布式锁

    Zookeeper实现分布式锁原理

    使用zookeeper创建临时序列节点来实现分布式锁,适用于顺序执行的程序,大体思路就是创建临时序列节点,找出最小的序列节点,获取分布式锁,程序执行完成之后此序列节点消失,通过watch来监控节点的变化,从剩下的节点的找到最小的序列节点,获取分布式锁,执行相应处理,依次类推……

    Maven依赖

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

    创建Lock接口

    public interface Lock {
        //获取到锁的资源
        public void getLock();
        // 释放锁
        public void unLock();
    }

    创建ZookeeperAbstractLock抽象

    //将重复代码写入子类中..
    public abstract class ZookeeperAbstractLock implements Lock {
        // zk连接地址
        private static final String CONNECTSTRING = "127.0.0.1:2181";
        // 创建zk连接
        protected ZkClient zkClient = new ZkClient(CONNECTSTRING);
        protected static final String PATH = "/lock";
    
        public void getLock() {
            if (tryLock()) {
                System.out.println("##获取lock锁的资源####");
            } else {
                // 等待
                waitLock();
                // 重新获取锁资源
                getLock();
            }
    
        }
    
        // 获取锁资源
        abstract boolean tryLock();
    
        // 等待
        abstract void waitLock();
    
        public void unLock() {
            if (zkClient != null) {
                zkClient.close();
                System.out.println("释放锁资源...");
            }
        }
    
    }

    ZookeeperDistrbuteLock

    public class ZookeeperDistrbuteLock extends ZookeeperAbstractLock {
        private CountDownLatch countDownLatch = null;
    
        @Override
        boolean tryLock() {
            try {
                zkClient.createEphemeral(PATH);
                return true;
            } catch (Exception e) {
    //            e.printStackTrace();
                return false;
            }
    
        }
    
        @Override
        void waitLock() {
            IZkDataListener izkDataListener = new IZkDataListener() {
    
                public void handleDataDeleted(String path) throws Exception {
                    // 唤醒被等待的线程
                    if (countDownLatch != null) {
                        countDownLatch.countDown();
                    }
                }
                public void handleDataChange(String path, Object data) throws Exception {
    
                }
            };
            // 注册事件
            zkClient.subscribeDataChanges(PATH, izkDataListener);
            if (zkClient.exists(PATH)) {
                countDownLatch = new CountDownLatch(1);
                try {
                    countDownLatch.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // 删除监听
            zkClient.unsubscribeDataChanges(PATH, izkDataListener);
        }
    
    }

    使用Zookeeper运行效果

    public class OrderService implements Runnable {
        private OrderNumGenerator orderNumGenerator = new OrderNumGenerator();
        // 使用lock锁
        // private java.util.concurrent.locks.Lock lock = new ReentrantLock();
        private Lock lock = new ZookeeperDistrbuteLock();
        public void run() {
            getNumber();
        }
        public void getNumber() {
            try {
                lock.getLock();
                String number = orderNumGenerator.getNumber();
                System.out.println(Thread.currentThread().getName() + ",生成订单ID:" + number);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unLock();
            }
        }
        public static void main(String[] args) {
            System.out.println("####生成唯一订单号###");
    //        OrderService orderService = new OrderService();
            for (int i = 0; i < 100; i++) {
                new Thread( new OrderService()).start();
            }
        }
    }
  • 相关阅读:
    ZOJ1450 BZOJ1136 BZOJ1137 HDU3932[最小圆覆盖]
    POJ 1755 Triathlon [半平面交 线性规划]
    POJ 3384 Feng Shui [半平面交]
    POJ 3525 Most Distant Point from the Sea [半平面交 二分]
    POJ 1279 Art Gallery [半平面交]
    POJ3335 POJ3130 POJ1474 [半平面交]
    POJ 3608 Bridge Across Islands [旋转卡壳]
    nginx访问量统计
    PV UV QPS 并发数
    PV、UV、IP之间的区别与联系
  • 原文地址:https://www.cnblogs.com/aaron911/p/10758384.html
Copyright © 2011-2022 走看看