Redisson简介
Redisson是一个用户Redis的Java客户端,可以让Java应用中使用Redis更加容易和直观。简化
Redis的基本操作,还提供了丰富的功能,比如:分布式锁、信号量、闭锁的高级特性。
Redisson分布式锁的作用
想象一个连锁超市的仓库管理系统,问题出在这里:
-
单店保安(synchronized)的问题:
每个分店都雇了一个保安(JVM锁),只能管自己仓库的货物。
问题场景:如果北京和上海分店同时抢着调拨全国最后一台电视,两个保安都认为"我这的电视可以卖",导致超卖。 -
总部调度系统(Redisson分布式锁):
总部给所有分店配了一个智能手环(Redisson),通过中央对讲机(Redis)协调:- 当任意分店要操作电视库存时,必须先喊:"总部,我要锁电视!"
- 如果总部回应:"锁成功",只有这个分店能操作,其他分店必须排队等待。
- 操作完成后必须喊:"总部,我释放电视锁!"(避免死锁)。
Redisson使用场景
场景1:多人同时下单可能导致库存扣减冲突,出现负库存问题。例如,用户A和用户B同时查询到
某商品库存为1,均下单成功但实际库存不足。
场景2:用户重复提交订单或支付回调并发处理时,可能生成重复订单或重复扣款。
场景3:定时任务(如每日库存同步、优惠券过期处理)在集群中多节点运行时,需避免重复执
行。
SpringBoot使用Redisson
导入依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.17.0</version>
</dependency>
配置Redis连接信息
spring:
data:
redis:
port: 6379
host: 127.0.0.1
# password: 123456
database: 0
# Redisson专属配置(可选)
redisson:
singleServerConfig:
connectionPoolSize: 10 # 最大连接数
idleConnectionTimeout: 10000 # 空闲超时(ms)
connectTimeout: 5000 # 连接超时(ms)
配置Redisson客户端
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://localhost:6379")
.setDatabase(0);
return Redisson.create(config);
}
}
编写测试案例
@RestController
public class RedissonDemoController {
@Autowired
private RedissonClient redissonClient;
// 分布式锁示例
@GetMapping("/lock")
public void testLock() {
//会在redis中添加一个Map数据类型,Map的key是myLock
RLock lock = redissonClient.getLock("myLock");
try {
// 尝试加锁,等待时间为10秒,过期时间为30秒
boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
if (isLocked) {
// 成功获取到锁,执行业务逻辑
System.out.println("获取锁成功,即将执行业务逻辑...");
Thread.sleep(30*1000);
} else {
// 加锁失败
System.out.println("获取锁失败,请稍后再试");
}
} catch (InterruptedException e) {
// 处理异常
} finally {
lock.unlock();
System.out.println("释放锁成功");
}
}
}
锁说明
boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
10
:表示尝试获取锁的操作将在最多10秒内处于等待状态尝试获取锁。如果在这10秒内锁变为可用(即当前没有其他客户端持有该锁),则此方法会成功获取锁并返回true
。30
:表示锁的最大保持时间是30秒。也就是说,即使获取到了锁,如果在30秒内没有主动释放锁(调用unlock
方法),锁也会自动释放,防止死锁的发生。TimeUnit.SECONDS
:指定上述两个参数的时间单位为秒。
如果锁的最大保持时间是-1,那么就会启用看门狗机制,每10秒自动续期锁的时间。
Redisson中的看门狗机制(Watchdog机制)用于自动续期分布式锁的有效期。当你使用Redisson
获取一个分布式锁但没有明确设置锁的过期时间(或者设置了特殊的值如-1),看门狗机制会自动
启动,并且在后台定期延长锁的过期时间。
默认情况下,如果一个锁被成功获取并且没有设定过期时间,Redisson的看门狗会每10秒检查一
次锁的状态,并将锁的有效期重置为30秒(这个时间可以通过配置进行调整)。这意味着,只要持
有锁的线程仍在运行并且没有主动释放锁,锁就会一直保持有效状态。
这种机制特别有用,因为在分布式系统中,有时很难准确预估完成临界区代码所需的时间。如果没
有看门狗机制,可能会因为预设的锁过期时间过短而导致锁提前释放,进而引发并发问题。而有了
看门狗机制,即使处理时间超过预期,只要任务还在执行,锁就不会过期,从而避免了这种情况的
发生。
但是需要注意的是,如果业务逻辑已经完成了对共享资源的操作,应该及时调用unlock()
方法来手
动释放锁,以便其他等待的线程可以获取锁并继续执行。否则,看门狗会持续续期锁,可能导致锁
长时间被占用的问题。