用到的redis命令
setnx(key, value):“set if not exits”,若该key-value不存在,则成功加入缓存并且返回1,否则返回0。
get(key):获得key对应的value值,若不存在则返回nil。
getset(key, value):先获取key对应的value值,若不存在则返回nil,然后将旧的value更新为新的value。
创建类RedisLock
package cn.xiaochi.redis;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
/**
* redis 分布式锁
*/
@Slf4j
@Component
public class RedisLock {
private StringRedisTemplate redisTemplate;
/**
* 加锁 用于处理秒杀
* @param key
* @param value 当前时间+超时时间
*/
public boolean lock(String key,String value){
// 为 true 表示获取锁
// setIfAbsent 对应 redis 中的 setnx
if (redisTemplate.opsForValue().setIfAbsent(key,value)){
return true;
}
String currentValue = redisTemplate.opsForValue().get(key);
// 如果锁过期
if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()){
// 获取上一个锁的时间
String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){
return true;
}
}
return false;
}
/**
* 解锁
* @param key
* @param value
*/
public void unlock(String key,String value){
try {
String currentValue = redisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(value) && currentValue.equals(value)) {
redisTemplate.opsForValue().getOperations().delete(key);
}
}catch (Exception e){
log.error("【redis分布式锁】解锁异常,{}",e);
// e.printStackTrace();
}
}
}
使用方式
package cn.xiaochi.redis;
import cn.xiaochi.redis.RedisLock;
public class RedisLock {
@Autowired
private RedisLock redisLock;
public static voidmain(){
int timeout = 10 * 1000;// 10秒
long time = System.currentTimeMillis() + timeout;
// 加锁
if(!redisLock.lock(productId,String.valueOf(time))){
throw new Exception("哎哟喂,人也太多了,换个姿势再试试");
}
// 秒杀商品逻辑处理 ...
// 解锁
redisLock.unlock(productId,String.valueOf(time));
}
}
网友评论