目录
2.1、使用reids的 watch + multi +exec 指令实现
2.2、使用reids的 watch + multi +exec + setnx(创建一个redis锁) 指令实现
2.3、使用redis的push/pop(List)指令实现
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.2、使用reids的 watch + multi +exec + setnx(创建一个redis锁) 指令实现
2.3、使用redis的push/pop(List)指令实现
使用redis的pop命令,如果能pop出来则证明还有库存,且秒杀成功,否则失败。
pop是原子性的,即使很高的并发,同时有很多用户访问,也是排队一个一个解决(并行转串行)

问题:一个用户的多条线程,都可能进入到秒杀接口,如果在第一条线程正在下单但还没有设置成功下单标记前,那么此时第二条线程依然可以进入到秒杀接口进行下单;
解决方案:在第一条线程进行减库存前,先设置排队标记;
设置排队标记有两个目的,一是让前端轮询结果时知道是处于排队状态。二是让一个用户的一条线程参与秒杀,而非多条。
my点评:这个直接用redis并行转串行就可以了
针对超卖的情况,只剩一个库存被某人秒杀到了,但这人发出了两个请求,相隔时间很短,因此,在进入我们秒杀逻辑的时候:
request01:判断库存ok--->创建订单ok--->减库存ok
request02:判断库存ok(request01还没减库存前读取到的)--->创建订单ok--->减库存ok
这会造成库存为负;
解决办法:
request02:判断库存ok--->设置人员id和商品id的唯一主键,提交
my点评:这个直接用redis并行转串行就可以了
2、少卖----库存有剩余
问题描述:预扣库存的流程为【请求----redis减库存----创建订单----支付】,若redis库存减了,但下单过程中创建订单失败怎么办?
解决办法:失败后就应该让Redis的库存再加上1;
本文探讨了电商场景下如何防止超卖和少卖的问题。针对超卖,提出了数据库字段设置为无符号整数、SQL语句判断库存、乐观锁等方法,以及Redis的watch、multi-exec、setnx和List指令的应用。对于少卖问题,重点在于处理预扣库存失败的情况,建议使用Redis进行库存调整以确保库存准确性。

4601

被折叠的 条评论
为什么被折叠?



