分布式锁遇锁等待_分布式锁—zookeeper高效实现

单个jvm的线程安全问题可以用lock锁或者synchronize解决,但是如何解决多个jvm的线程安全问题,这就要借助于分布式锁,分布式锁产生的原因是集群,主要场景:生成分布式全局订单号id。

在集群的情况下,多台机器需要共享一个全局count,这就需要分布式锁:

2bba4d256de51b9da2dbfe55284559ec.png

分布式锁常用的实现:

  • 数据库行锁(效率低,不推荐)
  • redis的redission(需要考虑思索,释放问题。繁琐一些)
  • Zookeeper实现 (使用临时节点,效率高,失效时间可以控制)

zk实现分布式锁的原理

使用zookeeper创建临时序列节点来实现分布式锁,思路就是创建临时序列节点,获取分布式锁,在未释放之前,其他应用不能创建相同路径节点,程序执行完成之后此临时节点消失,通过watch来监控节点的变化,其他应用可以重新获取,以此类推。。。

实现步骤

多个Jvm同时在Zookeeper上创建同一个相同的节点( /Lock),zk节点唯一的!节点类型为临时节点, jvm1创建成功时候,jvm2和jvm3创建节点时候会报错,该节点已经存在。这时候 jvm2和jvm3进行等待。 jvm1的程序现在执行完毕,执行释放锁。关闭当前会话,临时节点不复存在了并且事件通知Watcher,jvm2和jvm3继续创建。

代码实现

创建锁接口

package com.toov5.Lock;public interface ExtLock {       //ExtLock基于zk实现分布式锁    public void  getLock();        //释放锁    public void unLock();    }

模板方法

import org.I0Itec.zkclient.ZkClient;//将重复代码抽象到子类中(模板方法设计模式)public abstract class ZookeeperAbstractLock implements ExtLock {    private static final String CONNECTION="192.168.91.5:2181";    protected ZkClient zkClient = new ZkClient(CONNECTION);    private String lockPath="/lockPath";         //获取锁      public void getLock() {           //1、连接zkClient 创建一个/lock的临时节点          // 2、 如果节点创建成果,直接执行业务逻辑,如果节点创建失败,进行等待           if (tryLock()) {            System.out.println("#####成功获取锁######");        }else {            //进行等待            waitLock();        }        //3、使用事件通知监听该节点是否被删除,如果是,重新进入获取锁的资源         }         //创建失败 进行等待    abstract void waitLock();    abstract boolean tryLock();         //释放锁      public void unLock() {        //执行完毕 直接连接          if (zkClient != null) {            zkClient.close();            System.out.println("######释放锁完毕######");        }            }      }

接口方法实现类

package com.toov5.Lock;import org.I0Itec.zkclient.ZkClient;//将重复代码抽象到子类中(模板方法设计模式)public abstract class ZookeeperAbstractLock implements ExtLock {    private static final String CONNECTION="192.168.91.5:2181";    protected ZkClient zkClient = new ZkClient(CONNECTION);    private String lockPath="/lockPath";         //获取锁      public void getLock() {           //1、连接zkClient 创建一个/lock的临时节点          // 2、 如果节点创建成果,直接执行业务逻辑,如果节点创建失败,进行等待           if (tryLock()) {            System.out.println("#####成功获取锁######");        }else {            //进行等待            waitLock();        }             //3、使用事件通知监听该节点是否被删除    ,如果是,重新进入获取锁的资源              }         //创建失败 进行等待    abstract void waitLock();    abstract boolean tryLock();              //释放锁      public void unLock() {        //执行完毕 直接连接          if (zkClient != null) {            zkClient.close();            System.out.println("######释放锁完毕######");        }            }      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值