springboot 结合mysql、redis+lua 实现库存扣减方案,防止超卖
表结构
库存表:
订单表:
方案1:采用mysql 自带行级锁
select * from t_stock for update;
当前事务提交之后,其他线程才能获取锁。判断库存是否大于或等于当前需要购买的数量,否则返回库存不足。
@Transactional
@Override
public int createOrderForUpdate(Integer productId, Integer count) {
Stock stock = stockMapper.selectForUpdate(productId);
if (stock.getStock() < count) {
throw new StockLackException("库存不足");
}
Order order = new Order();
order.setUserId((int) Thread.currentThread().getId());
order.setProductId(productId);
order.setCount(count);
order.setOrderTime(new Date());
// 创建订单
baseMapper.insert(order);
// 扣减库存
stockMapper.stockForUpdate(stock.getId(), count);
return 1;
}
方案2:基于版本号的乐观锁
update t_stock set stock = stock - #{count}, version = version + 1
where version = #{version} and stock >= #{count} and id = #{id}
返回结果为此次更新影响的行数,如果影响的行数大于0,表示此次更新库存充足,否则返回库存不足。
@Transactional
@Override