java 客户端加锁_JAVA 基于Redis的分布式锁

本文详细介绍了如何在JAVA中利用Redis实现分布式锁,重点讲解了使用RedisTemplate的setIfAbsent方法进行加锁,并探讨了设置锁过期时间的重要性,以及提供了两种解锁方法,包括直接删除和使用Lua脚本确保安全解锁。
摘要由CSDN通过智能技术生成

80c9b7f57cb68968943ac9a46518a39e.png

分布式锁一般有三种实现方式:

数据库乐观锁

基于ZooKeeper的分布式锁

基于Redis的分布式锁

这里主要记录下基于Redis的分布式锁

Redis加锁

springboot2.1以后的版本可以直接使用redisTemplate提供的setIfAbsent方法进行加锁 相当于使用redis命令:SET key value [EX seconds] [PX millisecounds] [NX|XX]

redisTemplate.opsForValue().setIfAbsent(key,value,time,TimeUnit)

为什么是set命令而不是setNx命令?

因为setNx 无法设置key过期时间 需要通过expire来为key设置过期时间,意味着加锁是两条命令,不满足原子性。

锁的过期时间设置多少合适,是否可以不设置?

锁的过期时间一定是要有的,不然留着过年么?过期时间根据具体的业务逻辑来设置,但是一定要大于代码执行的时间。例如:

//加锁 锁的过期时间为5秒

Boolean lock = redisTemplate.opsForValue().setIfAbsent("111", "11", 5, TimeUnit.SECONDS);

if(lock){

System.out.println("业务逻辑执行在0-8秒范围内");

}

这个时候肯定是不合适的。

Redis解锁

加锁之后,一定要保证锁的释放,所以通常是在finally代码块里面释放锁。

获取到锁才释放锁,没有获取到,不要去释放锁,避免释放其他客户端加的锁。

释放锁的时候可以判断锁的持有者是否是自己,是自己的才进行释放。(2和3至少要遵循一个,这样才能避免误释放锁)

解锁方式一:

redisTemplate.delete(key)

解锁方式二:使用lua脚本

if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end

完整的加锁解锁代码如下:

@Autowired

RedisTemplate redisTemplate;

@Test

public void testLock() throws UnknownHostException {

String key = "lockTest";

InetAddress ia = InetAddress.getLocalHost();

String value = ia.toString();

//加锁 锁的过期时间为20秒

Boolean lock = redisTemplate.opsForValue().setIfAbsent(key, value, 20, TimeUnit.SECONDS);

if (!lock) {

//未获取到锁,直接返回

return;

}

try {

System.out.println("业务逻辑执行在小于20秒范围内");

} catch (Exception e) {

System.out.println("业务错误信息");

} finally {

// 方式一 直接使用del

redisTemplate.delete(key);

// 方式二 使用lua脚本

String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

RedisScript redisScript = new DefaultRedisScript(script);

List keys = new ArrayList<>();

keys.add(key);

redisTemplate.execute(redisScript, keys, value);

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值