package com.redis;
/**
* @author linn
* @date 2024年04月23日 15:31
*/
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfig {
@Bean(destroyMethod="shutdown")
public RedissonClient redissonClient() {
Config config = new Config();
config.setLockWatchdogTimeout(2000);
config.setNettyThreads(5);
config.setKeepPubSubOrder(true);
config.setMaxCleanUpDelay(2000);
config.setMinCleanUpDelay(200);
config.setThreads(5);
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
}
RedissonConfig配置类如上:
以下是测试类:
package com.redis;
/**
* @author linn
* @date 2024年04月23日 16:09
*/
import com.DemoApplication;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* @ClassName RedissonTest
* @Description Redisson测试用例
* @Author 阿Q
* @Date 2022/11/26
*/
@Slf4j
@SpringBootTest(classes = DemoApplication.class)
public class RedissonTest {
@Resource
private RedissonClient redissonClient;
@Resource
private ThreadPoolTaskExecutor executor;
// redisson分布式锁的key
private static final String LOCK_TEST_KEY = "redisson:lock:test";
private static final String LOCK_TITLE = "redisLock_";
int n = 500;
/**
* 分布式锁测试用例
*/
@Test
public void lockTest() {
// 利用 循环+多线程 模仿高并发请求
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
// 这里获取公平锁,遵循先进先出原则,方便测试
RLock fairLock = redissonClient.getFairLock(LOCK_TEST_KEY);
try {
// 尝试加锁
// waitTimeout 尝试获取锁的最大等待时间,超过这个值,则认为获取锁失败
// leaseTime 锁的持有时间,超过这个时间锁会自动失效(值应设置为大于业务处理的时间,确保在锁有效期内业务能处理完)
boolean lock = fairLock.tryLock(3000, 30, TimeUnit.MILLISECONDS);
if (lock){
log.info("线程:" + Thread.currentThread().getName() + "获得了锁");
log.info("剩余数量:{}", --n);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
log.info("线程:" + Thread.currentThread().getName() + "准备释放锁");
// 注意,无论出现任何情况,都要主动解锁
fairLock.unlock();
}
});
}
try {
// ->_-> 这里使当前方法占用的线程休息10秒,不要立即结束
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//加锁
public boolean acquire(String lockName) {
//声明key对象
String key = LOCK_TITLE + lockName;
//获取锁对象
RLock mylock = redissonClient.getLock(key);
//加锁,并且设置锁过期时间3秒,防止死锁的产生 uuid+threadId
mylock.lock();
boolean flag = mylock.isLocked();
//加锁成功
return true;
}
//锁的释放
public void release(String lockName) {
//必须是和加锁时的同一个key
String key = LOCK_TITLE + lockName;
//获取所对象
RLock mylock = redissonClient.getLock(key);
//释放锁(解锁)
mylock.unlock();
System.out.println("释放锁成功!"+key);
}
@Test
public void releaseTest(){
acquire("test_lock");
release("test_lock");
}
}
properties的配置类:
redisson.config=classpath:redisson.yaml
redisson.yaml配置类如下:
# 单一 Redis 服务器模式
singleServerConfig:
# Redis 服务器的地址
address: "redis://127.0.0.1:6379"
# 连接池的大小
connectionPoolSize: 64
# Redis 服务器的密码
password:
# Redis 数据库索引
database: 0
# 客户端名称
clientName:
# 超时时间,单位为毫秒
timeout: 3000
# Redis 命令失败重试次数
retryAttempts: 3
# 两次命令之间重试的时间间隔,单位为毫秒
retryInterval: 1500
# 发布和订阅的连接的最小数量
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅的连接池的大小
subscriptionConnectionPoolSize: 50
# 当前处理 Redis 命令的线程共享的联接
connectionMinimumIdleSize: 10
# 集群模式的配置 (需要注释或删除 singleServerConfig 当使用此模式)
#clusterServersConfig:
# scanInterval: 2000
# slaveConnectionPoolSize: 64
# slaveConnectionMinimumIdleSize: 24
# masterConnectionPoolSize: 64
# masterConnectionMinimumIdleSize: 24
# readMode: "SLAVE"
# nodeAddresses:
# - "redis://127.0.0.1:7001"
# - "redis://127.0.0.1:7002"
# - "redis://127.0.0.1:7003"
# password: "your_password"
# 其他模式,如 sentinel, masterSlave, replicated 可以在这里配置,但确保只有一个模式处于未注释状态
# 线程工厂配置
threads: 16
nettyThreads: 32
# 编解码器配置,默认是 Jackson
codec: !<org.redisson.codec.JsonJacksonCodec> {}
# 传输模式,默认是 NIO
transportMode: "NIO"
pom.xml配置文件:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.10.5</version>
</dependency>
应用到自己项目中的截图如下:
finally释放锁:
redisson加的锁和普通redis.setnx不同,数据结构不同: