springboot zookeeper实现分布式锁

分布式锁有多重实现方式,比如数据库 、 redis都可以实现。作为分布式协同工具zookeeper也可以实现分布式锁。

1、实现思路

  1. 每个客户端往/Locks下创建临时有序节点,/Locks/Lock_ 创建成功后/Locks下面会有每个客户端对应的节点,比如 /Locks/Lock_000001
  2. 客户端取得/Locks下的子节点,并进行排序,判断在最前面的是否为自己,如果自己的锁节点在第一位,代表获得锁成功。
  3. 如果自己的锁节点不再第一位,则监听自己前一位的锁节点。例如, 自己锁节点/Lock_000002,那么则监听Lock_000001
  4. 当前一位锁节点(Lock_000001)对应的客户端执行完成,释放锁,将会触发监听客户端(Lock_0000002) 的逻辑
  5. 监听客户端重新执行第2步逻辑,判断自己是否获得了锁

监听机制,临时有序节点



public class Mylock{
    //zk的连接串
    String IP = "127.0.0.1:2181";
   //计数器对象
   CountDownLatch countDownLatch = new CountDownLatch(1);
   
   //zk配置信息
   Zookeeper zooKeeper;
   private static final String LOCK_ROOT_PATH = "/Locks";
    private static final String LOCK_NODE_PATH = "Lock_";
    
    private String lockPath;
    
    //打开zookeeper的链接
    public MyLock(){
        try{
        zooKeeper = new ZooKeeper(IP,5000,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 Exception{
    //创建锁节点
    createLock();
    //尝试获取锁
    attempLock();
}

//创建锁节点
public void createLock() throws Exception{
    //1、打开zookeeper连接

    //2、创建Locks根节点(创建前先用exit判断是否存在,不存在创建)
   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);
    }
    
   // 3、创建临时有序节点
  lockPath = zooKeeper.create(LOCK_ROOT_PATH + "/" +LOCK_NODE_PATH,new byte[0] ,
             ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
 
 System.out.println("创建节点成功~~~" + lockPath);
 //进行测试一下~~,看看我们的代码是否有问题~~
}
    
}

  • 尝试获取锁
//监视器对象,监视上一个节点是否被删除\
Watcher watcher = new Watcher(){
    @Override
    public void proccess(WatcherEvent event){
        if(event.getType()==EventType.NodeDeleted){
            sychronized(this){
                notifyAll();
            }
        }
    }
}



private void attempLock() throws Exception{

//1、获取locks下的所有子节点 

List<String> list = zookeeper.getChildren(LOCK_ROOT_PATH,false);

//2、对子节点进行排序

Collections.sort(list);


//3、截取掉前面部分

int index = list.indexOf(lockPath.substring(LOCK_ROOT_PATH.length()+1));

//4、对索引进行判断
if(index == 0) {
    System.out.ptintln("说明是第1位,获取锁成功!")
    return;
}eles{
    //获取上一个节点的路径
    String path = list.get(index-1);
    //监视上一个节点
    Stat stat = zookeeper.exists(LOCk_ROOT_PATH+"/"+path,watcher); //监视器对象,监视上一个节点是否被删除
    
    if(stat==null){
        //回调,尝试重新获得锁
        attempLock();
    }else{
        //阻塞等待
        synchronized(watcher){
            watcher.wait();
        }
        
        attempLock();
    }
}

}
  • 释放锁
public void releaseLock() throws Exception{
    //删除临时有序节点
    zooKeeper.delete(this.lockPath,-1);
    zooKeeper.close();
    System.out.println("锁已经释放了~~~);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值