Redisson 实现分布式锁
什么是锁、分布式锁?
锁:由于资源有限,我们要控制同一时间,只有某些线程能访问到资源。
Java 实现锁:synchronized 关键字、并发包中的类。
场景举例:用户加入队伍,如果多个线程同时执行了加入队伍的代码,那么就会出现用户重复加入队伍的问题。所以,我们要加锁,同一时间,只允许一个线程执行加入队伍的代码。
存在问题:只对单个 JVM 有效,如果程序部署在多台服务器上,还会出现资源访问的问题。
所以,我们需要使用分布式锁,控制分布式系统的资源访问。
Redisson 实现分布式锁
Redisson 是一个 Java 操作 Redis 的客户端,提供了大量的分布式数据集来简化对 Redis 的操作和使用,可以让开发者像使用本地集合一样使用 Redis,完全感知不到 Redis 的存在。
配置 Redisson
引入依赖
1
2
3
4
5<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.32.0</version>
</dependency>编写配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class RedissonConfig {
private String host;
private String port;
public RedissonClient redissonClient() {
// 1.创建配置
Config config = new Config();
String redisAddress = String.format("redis://%s:%s", host, port);
// 使用单个 Redis,没有开集群
config.useSingleServer().setAddress(redisAddress).setDatabase(1);
// 2.创建实例
return Redisson.create(config);
}
}测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private RedissonClient redissonClient;
void test() {
// list
RList<String> rList = redissonClient.getLis ("test-list");
rList.add("shameyang");
System.out.println("rList: " + rList.get(0));
rList.remove(0);
// map
RMap<String, Integer> rMap = redissonClientgetMap ("test-map");
rMap.put("yang", 10);
System.out.println("rMap: " + rMap.ge("yang"));
rMap.remove("yang");
}
实现分布式锁
1 | // 创建锁实例 |
存在逾期问题:如果加锁的代码没有执行完,锁释放了,其他线程也会获取锁,执行加锁代码。
逾期问题(看门狗机制)
针对逾期问题,Redisson 中提供了看门狗机制,即自动续期机制。
使用该机制,需要将 tryLock 的 leaseTime 参数设置为 -1
原理:
- 监听当前线程,默认过期时间为 30s,每 10s 续期一次(补到 30)
- 如果线程挂掉(debug 时间过长也会被当成服务器宕机),则不会续期
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ShameYang's Blog!