使用Redis做分布式锁遇到的一个问题

加锁代码很简单,lockName不存在时设值value,一分钟时间过期,redis可以保证原子性

public boolean lock(String lockName, String value) {
		return valueOperations.setIfAbsent(lockName, value, Duration.ofSeconds(60));
	}

解锁用redis脚本实现原子性,lockName和value作为脚本参数

public boolean unlock(String lockName, String value) {
        Long result = redisTemplate.execute(redisScript, Collections.singletonList(lockName), "value");
        return 1 == result;
	}

get lockName 的值与value比较,相等则删除(解锁),否则直接返回解锁成功

@Bean
    public DefaultRedisScript<Long> unlockScript() {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText("if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 1 end");
        redisScript.setResultType(Long.class);
        return redisScript;
    }

测试代码

		String lockName = "myLockName";
		String lockValue = "myLockValue";
		System.out.println("lock result: " + redisLock.lock(lockName, lockValue));
		System.out.println("unlock result: " + redisLock.unlock(lockName, lockValue));
lock result: true
unlock result: true

似乎加锁和解锁都成功了,但是redis里锁依然存在,没有被删除
在这里插入图片描述
原因在于springboot配置RedisTemplate采用了json序列化:

template.setValueSerializer(new GenericJackson2JsonRedisSerializer());

所以加锁时myLockName的值不是myLockValue而是"myLockValue",而解锁时执行的redis脚本的参数是不带双引号的,导致直接走到else逻辑返回1。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值