如何解决高并发下的超卖问题

1,超卖问题的话,我们一般是通过事务来解决,sql语句中直接将更新和查询放在一起,通过行锁

startTransaction();

try{

  int remainder = statement.query("select remainder from stock where stock_id='$STOCK_ID$'"; 得到此刻库存

  然后根据订单要求数量来进行比较,如果库存大于等于订单要求数量,就执行减坤村操作

}catch(Exception e){rollback();}

commit();   这个时候就出现超卖问题了,因为上面三个用户同时抢购的时候,进入这个事务,然后同时执行update操作,

行锁这个时候排他性,会将update操作串行化,所以最后就发生了超卖 就是上面是两步操作,所以不可以

2,简单的是将上面两句语句合并为一句 update stock set remainder=remainder-amount where stock_id='$STOCK_ID$' and $remainder>=$amount 这样就可以了

3,但是高并发下的情况又不一样了 因为太多的update 都需要等待锁,大量的请求超时

通过redis来减库存 

  a,监听相关物品的库存信息,事务开启前保证物品库存不被修改

  b,获取现有库存信息,判断满足条件

  c,如果满足就进行扣除操作

  d,如果第一步有人更新了物品库存信息,进行重试

  e,如果库存为0或者剩余库存不满足当前订单扣除数量就退出。

秒杀服务的实际操作版本:

  用户秒杀请求到达api网关,先到redis(没有了就做一个标记)中判断秒杀的商品是否库存售罄,如果售罄直接返回秒杀失败

  基于令牌桶算法的rateLimiter进行限流,得到令牌的请求才可以继续进入到下面的逻辑

  要调用下游秒杀服务的接口,因为网关的并发处理能力大于下游的秒杀服务的处理能力,所以要通过排队来限制涌入下游系统的流量,

  进入秒杀服务后,要考虑到分布式事务的问题,因为秒杀服务扣减库存,然后订单生成订单和邮寄的相关信息,要保证信息的一致性,采用MQ,可靠消息最终一致性方案 MQ事务消息来实现。

  mq发送方在秒杀服务中,本地事务执行成功以后,也就是扣减秒杀库存成功以后,就可以返回秒杀下单成功了

posted @ 2020-10-13 14:36  笨笨走了  阅读(1254)  评论(0编辑  收藏  举报