我是靠谱客的博主 刻苦灰狼,这篇文章主要介绍springboot项目创建笔记28 之《redis分布式锁》,现在分享给大家,希望可以做个参考。

一、添加工具类
RedisLockUtil.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.example.utils; import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.RedisScript; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; /** * redis分布式锁 * * @author user * */ @Component @Slf4j public class RedisLockUtil { @Autowired private StringRedisTemplate stringRedisTemplate; /** * 加锁 * * @param key * @param value * @param expireTime * @param timeUnit * @return */ public boolean lock(String key, String value, int expireTime, TimeUnit timeUnit) { // key不存在则创建存储key,key存在则返回null Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, value, expireTime, timeUnit); if (flag == null || flag == false) { log.info("锁({},{})失败,该锁已存在或加锁失败", key, value); return false; } else { log.info("锁({},{})成功", key, value); return true; } } /** * 释放锁 * * @param key * @param value * @return */ public boolean unlock(String key, String value) { // 使用lua脚本保证原子性 String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class); Long result = (Long) stringRedisTemplate.execute(redisScript, Arrays.asList(key), value); if (result == null || result == 0) { log.info("释放锁({},{})失败,该锁不存在或锁已经过期", key, value); return false; } else { log.info("释放锁({},{})成功", key, value); return true; } } }

说明:
1、这里注入的操作类是StringRedisTemplate,因为自己定义的RedisTemplate设置了redis键值对<K,V>的value序列化方式被设置成了json格式,所以程序set进redis的string类型值,序列化后会带两个引号。在后面执行lua脚本比较keys和argv时会有问题
2、释放锁时用了lua脚本,保证原子性
3、stringRedisTemplate.execute的value参数是String类型,不能传list
4、集群模式下keys只能传一个,否则会报错:CROSSSLOT Keys in request don't hash to the same slot,所有key必须在同一个哈希槽上

Constants.java添加一个前缀

复制代码
1
public static final String LOCK_KEY = "lock:";

 二、测试类
RedisLockTest.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package myboot; import java.util.concurrent.TimeUnit; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.example.base.Constants; import com.example.myboot.MybootApplication; import com.example.utils.RedisLockUtil; @RunWith(SpringRunner.class) @SpringBootTest(classes = MybootApplication.class) public class RedisLockTest { @Autowired RedisLockUtil redisLock; @Test public void redisLockTest() { String key = Constants.LOCK_KEY + "123"; String value = "123"; redisLock.lock(key, value, 3000, TimeUnit.SECONDS); } @Test public void redisUnlockTest() { String key = Constants.LOCK_KEY + "123"; String value = "123"; redisLock.unlock(key, value); } }

参考资料:
https://blog.csdn.net/qq_33591903/article/details/108278059
https://blog.csdn.net/fedorafrog/article/details/112893769

注:最新代码上传至https://github.com/csj50/myboot
 

最后

以上就是刻苦灰狼最近收集整理的关于springboot项目创建笔记28 之《redis分布式锁》的全部内容,更多相关springboot项目创建笔记28内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(149)

评论列表共有 0 条评论

立即
投稿
返回
顶部