库存超卖问题

背景

购物车内有多种商品并且同时结算。当高并发时,其中一个商品库存不足,如果都成功就会出现库存不足的商品会超卖

解决办法

redis+lua

利用redis+lua的原子性,一个脚本内判断多个商品是否库存充足,在批量扣除库存。因为原子性的原因,就不会被其他进程扣除剩余的库存。
可是就是需要将所有的商品库存数据都存入redis统一管理。

mysql事务

利用mysql事务的排他锁+sql的乐观锁去判断。

  • 事务的排他锁是为了执行顺序,阻塞其他线程的修改。
  • 乐观锁是为了判断库存是否充足。

举例:商品A库存只有2,商品B库存有20
此时小甲来结算,A2件,B2件。小乙来结算,A1件,B1件。
sql执行过程

#小甲
set autocommit=0;
begin;
update stock set stock = stock-2 where id=A and stock>=2;
update stock set stock = stock-2 where id=B and stock>=2;

#小乙
set autocommit=0;
begin;
update stock set stock = stock-1 where id=A and stock>=1;	
// 此语句会被排他锁阻塞,当小甲的事务被释放后才会执行
// 且update语句,是会先查后改,而且查还是当前读,所以会读到库存不满足,影响行数是0,此时就可以在业务上回滚事务了。
// stock>=1的语句就是一个乐观锁,如果不加就会把库存扣成-1,就导致了超卖
update stock set stock = stock-1 where id=B and stock>=1;

# 小甲小乙提交事务
commit;
commit;

如果小甲结算时是AB商品的顺序,小乙结算时是BA商品的顺序,就有可能导致死锁,所以最后还是按商品编号排序后在进行业务结算。

消息中间件+事务

所有的秒杀任务都放到一个队列中,且只有一个消费者,确保顺序执行。
不足:只有一个消费者显然会拉长执行时间,所以对客户体验是不好的。
改进成多个消费者,就会有N个消费者之间的并发,这种方式会也无中间件的可靠性要高。在加上mysql的事务和乐观锁就可以挡住了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值