购物车结算问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复粘贴 AI 生成的内容
jtping
V2EX    程序员

购物车结算问题

  •  1
     
  •   jtping 2021-01-07 14:22:58 +08:00 2737 次点击
    这是一个创建于 1744 天前的主题,其中的信息可能已经有所发展或是发生改变。

    购物车结算生成订单时,需要对购物车中每件商品进行库存校验,和库存预扣除

    我现在想到了两种方案

    第一种:

    是每次只获取一个商品的锁,然后查询判断库存,预扣除,然后释放锁,之后的商品都走一遍这个流程

    第二种:

    是一次性获取到所有需要结算的商品的锁,然后一次性查询出所有商品库存,进行库存判断,预扣除,然后释放所有的锁

    两种方法目前我能想到的利弊:

    第一种如果商品多了,访问数据库就会比较频繁,但是锁单件商品的时间短了

    第二种如果商品多了,访问数据库虽然不会很频繁,但锁持有的时间肯定比第一种方法要长(而且是所有需要结算商品的锁)

    哪种方法比较合适,或者有什么更好的方法

    希望各位大神指导指导

    12 条回复    2021-01-08 16:23:51 +08:00
    kop1989
        1
    kop1989  
       2021-01-07 14:29:54 +08:00
    从我的经验上,我推荐用第二种。
    因为真正的业务场景比你设想的要复杂。
    1 、有商品组合(套装)的可能。
    2 、有消费者凑单的可能。
    3 、有二级库的可能。
    jtping
        2
    jtping  
    OP
       2021-01-07 14:37:41 +08:00
    @kop1989 多谢指导 目前我也比较倾向第二种 但一次性持的锁过多会不会对后面等待的用户不太友好
    Mitt
        3
    Mitt  
       2021-01-07 14:42:05 +08:00
    @jtping #2 我没做过这类的,不过我觉得可以考虑把库存缓存到 redis 了,等真正订单处理完成后再同步到数据库里,这样你的锁代价就很低了
    kop1989
        4
    kop1989  
       2021-01-07 14:46:31 +08:00   1
    @jtping #2 这就要看你真正的业务需求(也就是预计的网站流量、商品规模而定)
    比如像京东这种庞然巨物,就需要同时支持消费者“如果 A 没了,那我就不要 B,但保留 C”,“如果 A 没货,我就不买了”,“A 没了,我依然要买其他”,“ABC 是个套装,我用了个套装优惠券”等需求。

    这时候如果你选择第一种,在数据链路层来卡死只锁单件商品,就会面临频繁的锁》扣库》释放》异常》锁》退库》释放。
    这时候造成的系统性能浪费未见得更低,以及会带来业务展现上的不稳定(消费者会面临这款产品的库存数量“频繁抖动”)。也增加了上层的业务实现复杂度。
    jtping
        5
    jtping  
    OP
       2021-01-07 14:53:17 +08:00
    @Mitt 多谢指导 我之前一直在考虑两种方法的利弊 没往这方面想
    jtping
        6
    jtping  
    OP
       2021-01-07 14:56:47 +08:00
    @kop1989 豁然开朗! 是我之前没考虑周全
    YouLMAO
        7
    YouLMAO  
       2021-01-07 19:10:50 +08:00
    jd, ali 都是 TCC 分布式事务, 不是数据库加锁的
    YouLMAO
        8
    YouLMAO  
       2021-01-08 00:40:35 +08:00 via Android
    如果 A 没了,那我就不要 B,但保留 C”,“如果 A 没货,我就不买了”,“A 没了,我依然要买其他 @kop1989 京东阿里哪个页面是这个逻辑?不符合中国人原理
    pinews
        9
    pinews  
       2021-01-08 10:22:50 +08:00
    小白来交流下,减库存这个操作,本身不就自带锁吗,第一种和第二种有什么区别?第二种怎么减少数据库访问了?不同的商品可以一块减?
    就算有区别,锁的总耗时没较少,也说不上增加吧,问题应该是解决总耗时吧。

    要解决总耗时只能用缓存数据库了啊,redis memcached mysql 的 memory 表都可以吧,

    另外如果处理订单除了减库存,还要减红包,发短信,发邮件,赠送积分,红包等等,那可以考虑协程异步处理(消息队列)了啊

    不知道说的对不对。
    jtping
        10
    jtping  
    OP
       2021-01-08 15:40:40 +08:00
    @pinews 假设购物车一次性结算 100 件商品

    第一种方法就要执行 100 遍 update 语句来更新每件商品的库存 每件商品执行一次 但每次只需要拿一件商品的锁

    第二种方法将 100 件商品库存用一个 update 语句更新 因为需要一起更新 所以就需要同时持有 100 件商品的锁

    大概是这么个意思
    pinews
        11
    pinews  
       2021-01-08 16:16:51 +08:00
    @jtping 如果所有商品减库存都是相同的,比如-1,的确可以一起 update,明白了

    那就考虑缓存数据库呗,期待你的结果。
    jtping
        12
    jtping  
    OP
       2021-01-08 16:23:51 +08:00
    @pinews
    哈哈其实不必都相同 批量 update 网上一找一大堆

    我目前用的是第二种方案 利弊上面也有大神说了
    关于   &nbs; 帮助文档     自助推广系统     博客     API     FAQ     Solana     2796 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 04:00 PVG 12:00 LAX 21:00 JFK 00:00
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86