zookeeper分布式锁设计

分布式锁设计

业务需求:为售票机设计分布式锁 ,多台机器同时售票,保证每台机器当前售票业务结束后,才可以开始下一次售票 。

思路:利用zookeeper临时有序节点的特性为每次售票生成唯一的识别(也就是00000000001,000000000002这种格式的字符串),对每个业务的识别进行排序后,设定排在第一个的识别为获取到锁的识别,只有获取到锁的售票业务才可以进行售票,否则就只能等待,直到排在前面的识别释放了锁(也就是前一个节点被删除),才可以获取到锁。

创建锁的工具类

public class MyLock {
    //计数器对象
    CountDownLatch countDownLatch = new CountDownLatch(1);
    String IP = "192.168.164.134:2181";
    ZooKeeper zooKeeper;
    private static final String LOCK_ROOT_PATH = "/locks";
    private static final String LOCK_NODE_PATH = "lock1_";
    private String lockPath = "";

    public MyLock() {
        try {
            zooKeeper = new ZooKeeper(IP, 500000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if (event.getType() == Event.EventType.None) {
                        if (event.getState() == Event.KeeperState.SyncConnected) {
                            System.out.println("连接创建成功");
                            countDownLatch.countDown();
                        }
                    }
                }
            });
            //阻塞线程直到连接成功
            countDownLatch.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取锁
    public void acquireLock() throws KeeperException, InterruptedException {
        //创建锁
        createLoke();
        //尝试获取锁
        attemptLock();
    }

    private void createLoke() throws KeeperException, InterruptedException {
        Stat stat = zooKeeper.exists(LOCK_ROOT_PATH, false);
        //判断根节点是否存在,不存在就创建
        if (stat == null) {
            zooKeeper.create(LOCK_ROOT_PATH, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
        lockPath = zooKeeper.create(LOCK_ROOT_PATH + "/" + LOCK_NODE_PATH, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
        System.out.println("节点创建成功" + lockPath);
    }

    private void attemptLock() throws KeeperException, InterruptedException {
        List<String> children = zooKeeper.getChildren(LOCK_ROOT_PATH, false);
        Collections.sort(children);
        //lockPath:/locks/lock_0000000000000001格式
        int indexOf = children.indexOf(lockPath.substring(LOCK_ROOT_PATH.length() + 1));
        if (indexOf == 0) {
            System.out.println("成功获取到锁");
            return;
        } else {
            String prePath = children.get(indexOf - 1);
            Stat stat = zooKeeper.exists(LOCK_ROOT_PATH +"/"+prePath, watcher);
            if (stat == null) {
                attemptLock();
            } else {
                synchronized (watcher) {
                    watcher.wait();
                }
                attemptLock();
            }
        }

    }

    Watcher watcher = new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            if (event.getType() == Event.EventType.NodeDeleted) {
                synchronized (this) {
                    watcher.notifyAll();
                }
            }
        }
    };

    //释放锁
    public void releaseLock() throws KeeperException, InterruptedException {
        //删除临时有序节点
        zooKeeper.delete(this.lockPath,-1);
        zooKeeper.close();
        System.out.println("锁已经释放"+this.lockPath);
    }

}

测试

public class TicketSeller {

    private void sell(){
        System.out.println("售票开始。。。。。。。。。。。");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("售票结束#######################################################");
    }

    private void sellTicketWithLoke() throws KeeperException, InterruptedException {
        MyLock myLock = new MyLock();
        //获取锁
        myLock.acquireLock();

        sell();

        //释放锁
        myLock.releaseLock();

    }


    public static void main(String[] args) throws KeeperException, InterruptedException {
        TicketSeller ticketSeller= new TicketSeller();
        while (true){
            ticketSeller.sellTicketWithLoke();
        }

    }



}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桀骜浮沉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值