本文章记录的是秒杀库存的解决方案,解决并发问题。
@RestController
public class SpikeController {
@Autowired
private StringRedisTemplate redisTemplate;
private AtomicInteger successNum = new AtomicInteger(0);
@GetMapping("/init")
public String initSpike(){
// 初始化库存数量
redisTemplate.opsForValue().set("product_sku","5");
// 实际卖出数量 0
successNum.set(0);
return "初始化库存成功";
}
// 这样写 库存的 读写不具有原子性
// @GetMapping("/reducerSku")
// public String reducerSku(){
// System.out.println("被访问");
// Integer sku = Integer.parseInt(redisTemplate.opsForValue().get("product_sku"));
//
// sku = sku - 1;
//
// if(sku < 0){
// return "库存不足";
// }
// redisTemplate.opsForValue().set("product_sku",sku.toString());
// return "减少库存成功 共减少 :" + successNum.incrementAndGet();
// }
// 使用 synchronized 关键字 虽然可以实现但是效率低
// @GetMapping("/reducerSku")
// public synchronized String reducerSku(){
// System.out.println("被访问");
// Integer sku = Integer.parseInt(redisTemplate.opsForValue().get("product_sku"));
//
// sku = sku - 1;
//
// if(sku < 0){
// return "库存不足";
// }
// redisTemplate.opsForValue().set("product_sku",sku.toString());
// return "减少库存成功 共减少 :" + successNum.incrementAndGet();
// }
//
// // 使用 redis 事务
// @GetMapping("/reducerSku")
// public synchronized String reducerSku(){
// redisTemplate.setEnableTransactionSupport(true);
//
// List<Object> result = redisTemplate.execute(new SessionCallback<List<Object>>() {
// @Override
// public List<Object> execute(RedisOperations operations) throws DataAccessException {
// operations.watch("product_sku");
// String product_sku1 = (String) operations.opsForValue().get("product_sku");
// System.out.println(product_sku1);
// Integer product_sku = Integer.parseInt(product_sku1);
// // 开启事务
// operations.multi();
// // 必要的空查询
// operations.opsForValue().get("product_sku");
//
// if (product_sku <= 0) {
// return null;
// } else {
// product_sku -= 1;
//
// operations.opsForValue().set("product_sku", product_sku.toString());
//
// return operations.exec();
// }
// }
// });
//
// if(result == null || result.size() <= 0){
// return "库存不足";
// }
//
// return "减少库存成功 共减少 :" + successNum.incrementAndGet();
// }
@GetMapping("/reducerSku")
public synchronized String reducerSku(HttpServletRequest request){
System.out.println("被访问 :" + request.getRemoteAddr() + ":" + request.getRemoteHost());
Integer sku = Integer.parseInt(redisTemplate.opsForValue().get("product_sku"));
sku = sku - 1;
if(sku < 0){
return "库存不足";
}
redisTemplate.opsForValue().decrement("product_sku");
return "减少库存成功 共减少 :" + successNum.incrementAndGet();
}
@GetMapping("/successNum")
public String getSuccessNum(){
return "顾客成功抢到的数量是 :" + successNum.get();
}
}