电商系统库存相关问题解决方案

1、什么时候扣库存?

可以在下单的时候扣库存,也可以在支付成功之后再扣库存。
对于下单时扣库存,主要会存在被恶意下单的可能,有可能会被人把商品全部下单但是不支付。虽然可以通过设置订单的超时时间,等到了时间后如果还没有支付就把该订单失效恢复库存来解决。但是在超时时间这一段时间内,真正有需要租赁的客户还是下不了单,必须等超时之后才能下单,导致用户体验不好,同时对于商家来说也会丢失潜在的交易。也可以限制同一用户或同一IP下单的商品数量,但还是会存在问题,具体限制多大?假设限制为1,但可能有人确实需要租两件,而因为这个限制下不了单,同样会降低用户体验。对于支付成功再扣库存这种方式只需要保证不会出现超售情况就行。

2、怎么保证并发情况下不会出现下单超售现象?

主要有以下几种解决方案:

  1. 更新库存时再判断一遍库存是否与之前查找的库存一致,如update product set stock = stock - 1 where stock = old_stock and id = xxx。这种方式在并发度较高的情况下很容易产生冲突,需要重新去查询库存再做处理,导致MySQL压力过大,浪费资源。
  2. 在业务层通过sychronized加锁,将查询库存与更新库存放在sychronized代码块中执行,保证每个下单请求串行处理。这种方式会导致即使是不同的商品的修改库存请求拿不到锁时也会被阻塞,并发度不够,无法充分利用系统资源。同时,如果服务是分布式的,当多个请求被不同的服务节点处理时,还是有可能出现超售或其他线程安全问题。
  3. 使用Redis做分布式锁,在查询库存和更新库存前需先拿到分布式锁才允许进行处理。加锁时使用商品id相关的字符串作为key,这样可以保证对同一件商品的修改库存操作串行处理,不同商品的修改库存请求可以并行处理。并且即时服务是分布式的也能保证线程安全问题。

3、怎么使用Redis实现分布式锁?

在Redis中可以通过setnx key value来实现分布式锁,setnx的语义是指set not exist,只有当key不存在时,set才会成功。基于这个特点,可以将商品的id作为key(实际使用中一般会加前缀,方便管理,防止与其他key重名),value任意取一个值去setnx,如果失败则说明已经有其他线程获取了锁,当前线程可以自旋重试。如果成功则说明获取锁成功,可以开始去处理库存相关的逻辑,处理完后再把这个key删除,表示释放锁。

4、怎么保证能释放锁成功?

可以把删除key的操作放在finally语句块中,这样即使服务出现异常也能释放锁。但是不排除服务直接宕机的情况,所以还应该给key设置一个合理的有效期,保证过了有效期key能自动删除。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值