电商策略2----超卖、少卖

目录

1、超卖----库存为负

一、数据库:

1.1、字段设置为:unsigned+无符号整数

1.2、sql语句上进行判断,是否库存大于0

1.3、数据库乐观锁----version版本号

二、redis:

2.1、使用reids的  watch + multi +exec 指令实现

2.2、使用reids的 watch + multi +exec + setnx(创建一个redis锁) 指令实现

2.3、使用redis的push/pop(List)指令实现

2、少卖----库存有剩余 


1、超卖----库存为负

问题描述:在高并发下,多个线程并发更新库存,导致库存为负的情况;

一、数据库:

1.1、字段设置为:unsigned+无符号整数

把库存字段改为unsigned,这样可以保证库存不为负数,如果并发情况下被扣为负数的时候会报错,这个时候try catch然后返回库存不足就可以了;

1.2、sql语句上进行判断,是否库存大于0

使用 case when 判断语句,例如:

update test_db set count = case when count >=1 then count-1 else count end

1.3、数据库乐观锁----version版本号

就是在数据库中加一个version字段来表示版本号,修改库存时先获取当前版本号,然后修改时就传入该版本号并且对当前版本号+1,这种相较于第一种就更科学,在性能上更优越,而且对于流量较大的秒杀场景而言容错率更高。

二、redis:

思路:一是redis自带的队列(redis是单线程的,故而可以并行转串行);

           二是redis自身的事务机制;

2.1、使用reids的  watch + multi +exec 指令实现

电商策略2----超卖、少卖_第1张图片

2.2、使用reids的 watch + multi +exec + setnx(创建一个redis锁) 指令实现

2.3、使用redis的push/pop(List)指令实现

使用redis的pop命令,如果能pop出来则证明还有库存,且秒杀成功,否则失败。

pop是原子性的,即使很高的并发,同时有很多用户访问,也是排队一个一个解决(并行转串行

电商策略2----超卖、少卖_第2张图片

问题:一个用户的多条线程,都可能进入到秒杀接口,如果在第一条线程正在下单但还没有设置成功下单标记前,那么此时第二条线程依然可以进入到秒杀接口进行下单;

解决方案:在第一条线程进行减库存前,先设置排队标记;

设置排队标记有两个目的,一是让前端轮询结果时知道是处于排队状态。二是让一个用户的一条线程参与秒杀,而非多条。

my点评:这个直接用redis并行转串行就可以了

针对超卖的情况,只剩一个库存被某人秒杀到了,但这人发出了两个请求,相隔时间很短,因此,在进入我们秒杀逻辑的时候:

request01:判断库存ok--->创建订单ok--->减库存ok

request02:判断库存ok(request01还没减库存前读取到的)--->创建订单ok--->减库存ok

这会造成库存为负;

解决办法:

request02:判断库存ok--->设置人员id和商品id的唯一主键,提交

my点评:这个直接用redis并行转串行就可以了

2、少卖----库存有剩余 

问题描述:预扣库存的流程为【请求----redis减库存----创建订单----支付】,若redis库存减了,但下单过程中创建订单失败怎么办?

解决办法:失败后就应该让Redis的库存再加上1;

你可能感兴趣的:(运行过程类)