基于redis的setnx()、get()、getset()方法的分布式锁

10 篇文章 0 订阅

使用redis的setnx()、get()、getset()方法,用于分布式锁
1. setnx(lockkey, 当前时间+过期超时时间) ,如果返回1,则获取锁成功;如果返回0则没有获取到锁,转向2。

  2. get(lockkey)获取值oldExpireTime ,并将这个value值与当前的系统时间进行比较,如果小于当前系统时间,则认为这个锁已经超时,可以允许别的请求重新获取,转向3。

  3. 计算newExpireTime=当前时间+过期超时时间,然后getset(lockkey, newExpireTime) 会返回当前lockkey的值currentExpireTime。

  4. 判断currentExpireTime与oldExpireTime 是否相等,如果相等,说明当前getset设置成功,获取到了锁。如果不相等,说明这个锁又被别的请求获取走了,那么当前请求可以直接返回失败,或者继续重试。

  5. 在获取到锁之后,当前线程可以开始自己的业务处理,当处理完毕后,比较自己的处理时间和对于锁设置的超时时间,如果小于锁设置的超时时间,则直接执行delete释放锁;如果大于锁设置的超时时间,则不需要再锁进行处理。

private static final Integer Lock_Timeout = 3;

private Jedis jedis;

/**

  • 外部调用加锁的方法

  • @param lockKey 锁的名字

  • @param timeout 超时时间(放置时间长度,如:5L)

  • @return
    */
    public boolean tryLock(String lockKey, Long timeout) {
    try {
    Long currentTime = System.currentTimeMillis();//开始加锁的时间
    boolean result = false;

     while (true) {  
         if ((System.currentTimeMillis() - currentTime) / 1000 > timeout) {//当前时间超过了设定的超时时间  
             System.out.println("Execute DistributedLockHandler.tryLock method, Time out.");  
             break;  
         } else {  
             result = innerTryLock(lockKey);  
             if (result) {  
                 break;  
             } else {  
                 System.out.println("Try to get the Lock,and wait 100 millisecond....");  
                 Thread.sleep(100);  
             }  
         }  
     }  
     return result;  
    

    } catch (Exception e) {
    System.out.println(“Failed to run DistributedLockHandler.getLock method.”+ e);
    return false;
    }
    }

/**

  • 释放锁
  • @param lockKey 锁的名字
    */
    public void realseLock(String lockKey) {
    if(!checkIfLockTimeout(System.currentTimeMillis(), lockKey)){
    jedis.del(lockKey);
    }
    }

/**

  • 内部获取锁的实现方法

  • @param lockKey 锁的名字

  • @return
    */
    private boolean innerTryLock(String lockKey) {

    long currentTime = System.currentTimeMillis();//当前时间
    String lockTimeDuration = String.valueOf(currentTime + Lock_Timeout + 1);//锁的持续时间
    Long result = jedis.setnx(lockKey, lockTimeDuration);

    if (result == 1) {
    return true;
    } else {
    if (checkIfLockTimeout(currentTime, lockKey)) {
    String preLockTimeDuration = jedis.getSet(lockKey, lockTimeDuration);
    if (currentTime > Long.valueOf(preLockTimeDuration)) {
    return true;
    }
    }
    return false;
    }

}

/**

  • 判断加锁是否超时
  • @param currentTime 当前时间
  • @param lockKey 锁的名字
  • @return
    */
    private boolean checkIfLockTimeout(Long currentTime, String lockKey) {
    if (currentTime > Long.valueOf(jedis.get(lockKey))) {//当前时间超过锁的持续时间
    return true;
    } else {
    return false;
    }
    }

public DistributedLockHandler setJedis(Jedis jedis) {
this.jedis = jedis;
return this;
}

public static void main(String[] args) {
Jedis jedis = new Jedis(“127.0.0.1”, 6379);

DistributedLockHandler distributedLockHandler = new DistributedLockHandler().setJedis(jedis);  
try{  
    boolean getLock = distributedLockHandler.tryLock(lockKey, Long.valueOf(5));  

    if(getLock){  
        // Do your job  
        System.out.println("Do your job........");  
    }  

}catch(Exception e){  
    System.out.println(e);  
}finally {  
    distributedLockHandler.realseLock(lockKey);  
}  

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值