购物车结算生成订单时,需要对购物车中每件商品进行库存校验,和库存预扣除
我现在想到了两种方案
第一种:
是每次只获取一个商品的锁,然后查询判断库存,预扣除,然后释放锁,之后的商品都走一遍这个流程
第二种:
是一次性获取到所有需要结算的商品的锁,然后一次性查询出所有商品库存,进行库存判断,预扣除,然后释放所有的锁
两种方法目前我能想到的利弊:
第一种如果商品多了,访问数据库就会比较频繁,但是锁单件商品的时间短了
第二种如果商品多了,访问数据库虽然不会很频繁,但锁持有的时间肯定比第一种方法要长(而且是所有需要结算商品的锁)
哪种方法比较合适,或者有什么更好的方法
希望各位大神指导指导
1
kop1989 2021-01-07 14:29:54 +08:00
从我的经验上,我推荐用第二种。
因为真正的业务场景比你设想的要复杂。 1 、有商品组合(套装)的可能。 2 、有消费者凑单的可能。 3 、有二级库的可能。 |
3
Mitt 2021-01-07 14:42:05 +08:00
@jtping #2 我没做过这类的,不过我觉得可以考虑把库存缓存到 redis 了,等真正订单处理完成后再同步到数据库里,这样你的锁代价就很低了
|
4
kop1989 2021-01-07 14:46:31 +08:00 1
@jtping #2 这就要看你真正的业务需求(也就是预计的网站流量、商品规模而定)
比如像京东这种庞然巨物,就需要同时支持消费者“如果 A 没了,那我就不要 B,但保留 C”,“如果 A 没货,我就不买了”,“A 没了,我依然要买其他”,“ABC 是个套装,我用了个套装优惠券”等需求。 这时候如果你选择第一种,在数据链路层来卡死只锁单件商品,就会面临频繁的锁》扣库》释放》异常》锁》退库》释放。 这时候造成的系统性能浪费未见得更低,以及会带来业务展现上的不稳定(消费者会面临这款产品的库存数量“频繁抖动”)。也增加了上层的业务实现复杂度。 |
7
YouLMAO 2021-01-07 19:10:50 +08:00
jd, ali 都是 TCC 分布式事务, 不是数据库加锁的
|
8
YouLMAO 2021-01-08 00:40:35 +08:00 via Android
如果 A 没了,那我就不要 B,但保留 C”,“如果 A 没货,我就不买了”,“A 没了,我依然要买其他 @kop1989 京东阿里哪个页面是这个逻辑?不符合中国人原理
|
9
pinews 2021-01-08 10:22:50 +08:00
小白来交流下,减库存这个操作,本身不就自带锁吗,第一种和第二种有什么区别?第二种怎么减少数据库访问了?不同的商品可以一块减?
就算有区别,锁的总耗时没较少,也说不上增加吧,问题应该是解决总耗时吧。 要解决总耗时只能用缓存数据库了啊,redis memcached mysql 的 memory 表都可以吧, 另外如果处理订单除了减库存,还要减红包,发短信,发邮件,赠送积分,红包等等,那可以考虑协程异步处理(消息队列)了啊 不知道说的对不对。 |
10
jtping OP @pinews 假设购物车一次性结算 100 件商品
第一种方法就要执行 100 遍 update 语句来更新每件商品的库存 每件商品执行一次 但每次只需要拿一件商品的锁 第二种方法将 100 件商品库存用一个 update 语句更新 因为需要一起更新 所以就需要同时持有 100 件商品的锁 大概是这么个意思 |
11
pinews 2021-01-08 16:16:51 +08:00
|