1、 pom.xml中引入相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2、 定义获取redis锁和释放redis锁方法的工具类
package com.example.java8test;
import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@Slf4j
public class RedisUtils {
@Resource
private RedisTemplate<String,Object> redisTemplate;
/**
* 获取redis锁
* @param key 键
* @param value 当前时间 + 超时时间
* @return 是否成功获得锁
*/
public boolean lock(String key,String value){
Boolean success = redisTemplate.opsForValue().setIfAbsent(key,value);
if(null != success && success){
return true;
}
String currentValue = (String) redisTemplate.opsForValue().get(key);
//如果当前值不为空,且值小于系统时间,说明锁已过期(过期的锁由于某种原因未被删除)
if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()){
//当两个线程都满足上边的条件,进入该if语句,需要只有一个线程能够获得锁成功返回true,另一个返回false,
//所以需要用再次获取到的值与最开始的原值进行比较,相同才说明获得锁成功
String oldValue = (String) redisTemplate.opsForValue().getAndSet(key,value);
return StringUtils.isNotEmpty(oldValue) && oldValue.equals(currentValue);
}
return false;
}
public void unlock(String key,String value){
try {
String currentValue = (String)redisTemplate.opsForValue().get(key);
if(!StringUtils.isEmpty(currentValue) && currentValue.equals(value)){
redisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
log.error("redis unlock exception: {}", Throwables.getStackTraceAsString(e));
}
}
}
3、 在程序中使用redis锁
package com.example.java8test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/example")
@RestController
@Slf4j
public class ExampleController {
private static final String key = "example:redis:test:";
@Autowired
private RedisUtils redisUtils;
@PostMapping("/saveRecord")
public String saveRecord(String recordId){
//仅是为了演示如何使用redis锁
long time = System.currentTimeMillis();
boolean lock = redisUtils.lock(key + recordId,String.valueOf(time + 10 * 1000));
if(!lock){
return "fail";
}
try {
log.info("进行保存记录的相关操作");
return "success";
} catch (Exception e) {
log.error("saveRecord failed: {}",e);
return "fail";
} finally {
redisUtils.unlock(key + recordId,String.valueOf(time + 10 * 1000));
}
}
}
浙公网安备 33010602011771号