实现步骤
代码展示
// @Transactional(rollbackFor = Exception.class)
public void deduct(){
//1、查询库存信息并锁定库存信息
List<Stock> stocks = stockMapper.selectList(new QueryWrapper<Stock>().eq("product_code","1001"));
//这里取第一个库存
Stock stock = stocks.get(0);
//2、判断库存是否充足
if(stock != null && stock.getCount()>0){
//3、扣减库存是否充足
stock.setCount(stock.getCount()-1);
Integer version = stock.getVersion();
stock.setVersion(version + 1);
if(this.stockMapper.update(stock,new UpdateWrapper<Stock>().eq("id",stock.getId()).eq("version",version)) == 0 ){
//如果更新失败则重试
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.deduct();
}
stockMapper.updateById(stock);
}
}
注意
1、需要注释掉事务注解 (因为大量重试后会发生事务阻塞)
2、重试之前要睡一下(因为递归执行会导致栈内存溢出)
问题分析
1、高并发情况下,性能极低。
2、ABA问题
3、读写分离情况下导致乐观锁不可靠(主从库同步不及时,导致从库查询旧数据)