/**
* @email 930312043@qq.com
* @author: zhaoshuai
* @date: 2021/7/30 8:13
*/
@RestController
public class IndexController {
@Autowired
private Redisson redisson;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@RequestMapping("/deduct_stock")
public String deductStock() {
// 加一个简单的synchronized锁
synchronized(this) {
int stock = Integer . parseInt (stringRedisTemplate.opsForValue().get(" stock ")); // iedis. get(" stock" )
if (stock > 0) {
int realStock = stock - 1;
stringRedisTemplate.opsForValue().set(" stock ,realStock +”"); // iedis. set (key, value)
System.out.println("扣减成功,剩余库存:"+ realStock) ;
} else {
System.out.println("扣减失败,库存不足"):
}
}
return "end";
}
}
单单加一个synchronized锁是不可以的,synchronized是基于JVM的,而对于分布式的情况下,这种加锁方式事无效的。针对这做了一下调整:
/**
* @email 930312043@qq.com
* @author: zhaoshuai
* @date: 2021/7/30 8:13
*/
@RestController
public class IndexController {
@Autowired
private Redisson redisson;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@RequestMapping("/deduct_stock")
public String deductStock() {
String lockKey = "lockKey";
// Boolean result = stringRedisTemplate . opsForValue ().setIfAbsent(lockKey,"zhuge" ); // jedis. setnx(k, v)|
// stringRedisTemplate. expire (lockKey, timeout: 10, TimeUnit. SECONDS) ;
stringRedisTemplate. opsForValue(). setIfAbsent (lockKey,value: zhue, timeout: 10, TimeUnit. SECONDS);
if (!result) {
return "error_code";
}
try {
int stock = Integer . parseInt (stringRedisTemplate.opsForValue().get(" stock ")); // iedis. get(" stock" )
if (stock > 0) {
int realStock = stock - 1;
stringRedisTemplate.opsForValue().set(" stock ,realStock +”"); // iedis. set (key, value)
System.out.println("扣减成功,剩余库存:" + realStock);
} else {
System.out.println("扣减失败,库存不足"):
}
}finally {
stringRedisTemplate.delete(lockKey);
}
}
return "end";
}
以上这样做也是不可以的,针对于这个时间的问题。加锁时间&&业务执行的时间:当业务执行的时间大于锁的时间时,这时候stringRedisTemplate.delete(lockKey);
删除的可能是下一个事务的锁,依次下去,锁就永久失效了。
package com.kuaishou.`is`.ea.contract.api.config
/**
* @email 930312043@qq.com
* @author: zhaoshuai
* @date: 2021/7/30 8:13
*/
@RestController
public class IndexController {
@Autowired
private Redisson redisson;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@RequestMapping("/deduct_stock")
public String deductStock() {
String lockKey = "lockKey";
String clientId = UUID . randomUUID ().toString();
stringRedisTemplate.opsForValue().setIfAbsent(lockKey, value: zhue, timeout: 10, TimeUnit. SECONDS);
if (!result) {
return "error_code";
}
try {
int stock = Integer . parseInt (stringRedisTemplate.opsForValue().get(" stock ")); // iedis. get(" stock" )
if (stock > 0) {
int realStock = stock -1;
stringRedisTemplate.opsForValue().set(" stock ,realStock +”"); // iedis. set (key, value)
System.out.println("扣减成功,剩余库存:" + realStock);
} else {
System.out.println("扣减失败,库存不足"):
}
} finally {
if (clientId.equals(stringRedisTemplate.opsForValue().get(lockKey))
// 出现了卡顿,也可能删除别人的锁
stringRedisTemplate . delete (lockKey);
}
}
return "end";
}
可以再开启一个线程,为锁时间续命。
Redisson的基本使用:Redisson
分布式锁Redisson会面临一个性能的问题,我们这个时候就可以使用ConcurrentHashMap来解决这个问题。详解见JUC