1.setnx+过期时间实现
public void testLock() {
//从redis里面获取数据
String uuid = UUID.randomUUID().toString();
//1 获取当前锁 setnx + 设置过期时间
// Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent("lock", "lock");
Boolean ifAbsent =
redisTemplate.opsForValue()
.setIfAbsent("lock", uuid,3, TimeUnit.SECONDS);
//2 如果获取到锁,从redis获取数据 数据+1 放回redis里面
if(ifAbsent) {
//获取锁成功,执行业务代码
//1.先从redis中通过key num获取值 key提前手动设置 num 初始值:0
String value = redisTemplate.opsForValue().get("num");
//2.如果值为空则非法直接返回即可
if (StringUtils.isBlank(value)) {
return;
}
//3.对num值进行自增加一
int num = Integer.parseInt(value);
redisTemplate.opsForValue().set("num", String.valueOf(++num));
//3 释放锁 lua脚本实现
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//lua脚本
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
"then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
redisScript.setScriptText(script);
//设置返回结果
redisScript.setResultType(Long.class);
redisTemplate.execute(redisScript, Arrays.asList("lock"),uuid);
} else {
try {
Thread.sleep(100);
this.testLock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.Redisson
1.引入依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
</dependency>
2 .创建Redisson配置类
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.data.redis")
public class RedissonConfig {
private String host;
private String password;
private String port;
private int timeout = 3000;
private static String ADDRESS_PREFIX = "redis://";
/**
* 自动装配
*
*/
@Bean
RedissonClient redissonSingle() {
Config config = new Config();
if(!StringUtils.hasText(host)){
throw new RuntimeException("host is empty");
}
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(ADDRESS_PREFIX + this.host + ":" + port)
.setTimeout(this.timeout);
if(StringUtils.hasText(this.password)) {
serverConfig.setPassword(this.password);
}
return Redisson.create(config);
}
}
3.在业务方法编写加锁和解锁
@Autowired
private RedissonClient redissonClient;
//Redisson实现
@Override
public void testLock() {
//1 通过redisson创建锁对象
RLock lock = redissonClient.getLock("lock1");
//2 尝试获取锁
//(1) 阻塞一直等待直到获取到,获取锁之后,默认过期时间30s
lock.lock();
//(2) 获取到锁,锁过期时间10s
// lock.lock(10,TimeUnit.SECONDS);
//(3) 第一个参数获取锁等待时间
// 第二个参数获取到锁,锁过期时间
// try {
// // true
// boolean tryLock = lock.tryLock(30, 10, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
//3 编写业务代码
//1.先从redis中通过key num获取值 key提前手动设置 num 初始值:0
String value = redisTemplate.opsForValue().get("num");
//2.如果值为空则非法直接返回即可
if (StringUtils.isBlank(value)) {
return;
}
//3.对num值进行自增加一
int num = Integer.parseInt(value);
redisTemplate.opsForValue().set("num", String.valueOf(++num));
//4 释放锁
lock.unlock();
}