超卖现象一 :解决方式
1.扣除库存不在程序中进行,而在数据库中
2.向数据库传递库存增量,扣减1个库存,增量为-1
3.在数据库update语句计算库存,通过update行锁解决并发
超卖现象二:解决方案
1.校验库存,扣除库存统一加锁
2.使之成为原子操作
3.并发时,只有获得锁的线程才能校验,扣除库存
4.扣除库存结束后,释放锁
5.确保库存不会扣成负数
使用redisson 实现分布式锁------------------------------------------------------start-------------------------------------------------------------------------
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.12.0</version>
</dependency>
@Autowired private RedissonClient redissonClient;
/** * 分布式锁【3】 编写业务代码 * 1、Redisson是基于Redis,使用Redisson之前,项目必须使用Redis * 2、注意getLock方法中的参数,以specId作为参数,每个specId一个key,和 * 数据库中的行锁是一致的,不会是方法级别的锁 |
@Override @Transactional(propagation = Propagation.REQUIRED) public void decreaseItemSpecStock(String itemSpecId, Integer buyCounts) { /** * 1.查询库存为 * 2.判断库存是否减少到0以下 */ //锁 RLock lock = redissonClient.getLock("item_lock" + itemSpecId); //5s 发生异常会在5s释放锁/** * 1、获取分布式锁,锁的超时时间是5秒get * 2、获取到了锁,进行后续的业务操作 */
lock.lock(5, TimeUnit.SECONDS); try { int result = itemsMapperCustom.decreaseItemSpecStock(itemSpecId, buyCounts); if (result != 1) { throw new RuntimeException("订单创建失败,原因:库存不足!"); } } catch (RuntimeException e) { throw e; } finally { //解锁/** * 不管业务是否操作正确,随后都要释放掉分布式锁 * 如果不释放,过了超时时间也会自动释放 */
lock.unlock(); }
使用redisson 实现分布式锁------------------------------------------------------end-------------------------------------------------------------------------
来源:oschina
链接:https://my.oschina.net/u/4182459/blog/3275985