分布式锁之redis分布式锁

关于redis分布式锁加锁释放锁的代码如下,为什么这么写就不解释了

    //加锁
    private boolean redisLock(String lockKey, String uniqueValue, int seconds) {
        Jedis jedis = null;
        try {
            jedis = this.getJedis();
            String result = jedis.set(lockKey, uniqueValue, "NX", "EX", seconds);
            if ("OK".equals(result)){
                return true;
            }

        }finally {
            this.close(jedis);
        }

        return false;
    }
//释放锁
    public boolean redisUnlock(String lockKey, String uniqueValue) {
        Jedis jedis = null;
        try {
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            jedis = this.getJedis();
            Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(uniqueValue));
            if (result.equals(1L)){
                return true;
            }

        }finally {
            this.close(jedis);
        }

        return false;
    }
   
   /**
     *
     * @param lockKey 锁名
     * @param uniqueValue 唯一值
     * @param seconds 锁过期时间
     * @param retryCount 重试次数
     * @param sleepTime 重试间隔时间
     * @return
     */
    public boolean lockRetry(String lockKey, String uniqueValue, int seconds, int retryCount, Long sleepTime) {

        boolean flag = false;
        try {
            for (int i=0; i<retryCount; i++){
                flag = this.redisLock(lockKey, uniqueValue, seconds);

                if (flag) break;

                Thread.sleep(sleepTime);

            }
        }catch (Exception e){
            logger.error("lockRetry error,reason:", e);
        }

        return flag;
    }

使用方法如下

boolean getLock = lockRetry(..);
if(!getLock){
    //提示当前访问人数过多之类的
}

//拿到锁
execute your code

//最后释放锁
redisUnlock(..);

以下是个人理解
redis重试加锁,对于重试的间隔时间不好把控,时间太短,拿锁的线程还没有跑完,重试加锁肯定失败,时间太长,

可能已经被别的线程抢走了锁,导致到重试完指定次数都没有拿到锁!
不过,这种方式对于并发不算太高的还可以用,如果并发高的话就不太适用了。

如果是阻塞的方式会更好一些,获取不到锁线程阻塞,等到锁被释放去唤醒所有阻塞的线程,继续去争夺锁资源,

这样才是比较合理的!!那么就又回到单应用上去了,显然就没有意义了。

所以个人认为最好的方式还是增加重试次数(保证一定能拿到锁),重试间隔设置

短点(重试太长会导致线程完成任务的时间增加),这样才能保证每个线程都能正常完成任务!

举个例子:A拿到锁并执行了5秒(实际是不知道程序会执行多久,也无法估计),假设设置的重试间隔为8秒(大于5秒),

B拿不到锁等待8秒,A执行完毕5秒后释放了锁,B还在等待,等到
B继续去拿锁的时候锁已经被其他线程占用,导致B可能一直拿不到锁,所以重试间隔一定要小于程序执行时间!

 

大家有什么更好的想法,欢迎补充~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值