关于Redis(仅记录)
Redis分布式锁
@RequestMapping("/sub_stock")
public String subStock(){
String lockKey = "product_101";
String clientId = UUID.randomUUID().toString();
//Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey,"giao");//jedis.setnx(k,v)
//stringRedisTemplate.expire(lockKey, 10, TimeUnit.SECONDS);
Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 10, TimeUnit.SECONDS);
if(!result){
return "error_code";
}
try {
int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));//jedis.set(key,value)
if(stock > 0){
int realStock = stock -1;
stringRedisTemplate.opsForValue().set("stock",realStock +"");//jedis.set(key, value)
System.out.println("扣减成功,剩余库存:" + realStock);
}else {
System.out.println("扣减失败,库存不足");
}
} finally{
if(clientId.equals(stringRedisTemplate.opsForValue().get(lockKey))){
stringRedisTemplate.delete(lockKey);
}
}
return "end";
}
这样的写法仍有一些遗留问题,比如在极端场景下,中间代码还未执行完,key就已经过期。
我们可以引入Redisson来解决:
@Autowired
private Redisson redisson;
@RequestMapping("/sub_stock")
public String subStock(){
String lockKey = "product_101";
RLock redissonLock = redisson.getLock(lockKey);
try {
//真正加锁
redissonLock.lock();
int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));//jedis.set(key,value)
if(stock > 0){
int realStock = stock -1;
stringRedisTemplate.opsForValue().set("stock",realStock +"");//jedis.set(key, value)
System.out.println("扣减成功,剩余库存:" + realStock);
}else {
System.out.println("扣减失败,库存不足");
}
} finally{
redissonLock.unlock();
}
return "end";
}
Redisson分布式锁的实现原理图