1、在设计公司的库存架构的时候,出现了问题,当处理无座商品的时候,发现,回滚逻辑有问题,具体的逻辑为:
比如如果库存设置为1 ,则
(1) 用户1 下单成功,库存-1
(2)用户2下单因为库存 是0所以 下单失败,开始回滚,回滚的时候+1,导致目前的库存为 1(实际上这个库存已经被用户1买走了)
(3)用户3 下单成功 ,库存-1
最后:导致库存1 卖了2次,
原因分析:
回滚逻辑没有显示订单号,应该严格按照订单号回滚,否则会把别人的库存回滚掉;
大麦的逻辑设置:
首先第一步:
假设库存总量为total_count,本次用户下单的数量为10;
数据库有3列,总 total_count,已售: sale_count,剩余 marging_count;
这些都放在一个事务中
try{
1、查询订单库存,如果库存不足直接返回 查询的条件唯一(比如按照订单号)
2、将库存锁定比如 1是未锁定,2是锁定 则 设置当前的行为锁定状态;
update recrod set status=2 where status=1 and 条件;
3、如果需要修改的库存有多条,对需要修改的库存进行排序(防止死锁)
4、逐行设置库存:
update sale_count+10 ,margin_count-10 where 条件+status=2 and sale_count-10>=0;
} catch(Exception e){
}
之所以如此设置:
1、全部放在一个事务中,方便异常回滚,
2、使用一个status锁定状态,因为mysql是行锁,保证事务并发处理的时候只有个线程可以往后走,后面的线程会等待,处理一条数据,
3、指定一个唯一条件,比如按照订单号回滚,如果订单号不满足直接退出,防止回滚别人的库存
4、设置库存的时候,需要先进行排序,让线程顺序执行,防止死锁,举个栗子:
如果不排序:A,B两个线程 ,回滚库存 ,如果第一个A线程扣减了X1行,下一步执行Y1行,
但另一个线程B,扣减了Y1,下一步需要扣减X1行,这时候,
A线程占着X1行,需要等待B线程释放Y1行,
而同时B线程占着Y1行,等待着A线程释放X1行,
产生了死锁
所以必须要排序;
5、扣减的时候执行 条件添加:sale_count-10>=0; 保证即使某个地方有问题,也不会扣减为负数;
问题:1、sale_count-10>=0; 不是小于=0;
是的;
2、排序如何排序,根据什么条件排序 根据票品的ID进行排序,保证顺序;
3、我们的设置状态是锁定状态?那也就是每个库存都要设置一个是否锁定的状态? 还是专门设计一张表,锁定状态,卖座的优惠券发券如何设计
可以加一张新表把状态放进来;