最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 防止商品超卖的 3 个思路!

    正文概述 转载于:掘金(PHP开源社区)   2021-04-18   556

    前言

    在多个人同时对一个商品下单时,如果处理的不得当会存在超卖的现象,这种严重的bug是无法接受的。
    这是一种极为常见的并发问题,这个时候就有开发者想到了通过锁来控制。但是由于很多小伙伴对于锁没有一个充分的认识,最后却弄巧成拙。
    如下,我列举一些常见的解决思路和我的想法,请大家参考。

    一、如何防止超卖

    在防止超卖的逻辑编写时,加锁这个思路是没有问题的,但是要加什么锁,锁哪一段逻辑就成为了问题。

    1、思路1

    jvm提供了synchronized和reentrantlock。
    这两个锁适合在减库存的时候使用吗?
    理论上讲,是可以使用的,但是服务必须是单机部署。如果是多台服务器,就会变成如下场景,锁根本没有作用。

    防止商品超卖的 3 个思路!

    2、思路2

    jvm锁弊端很明显,这时就会想到分布式锁,分布式锁实现的方法有很多。
    我列举了下redis和zk的实现及其对比,这种方式不管是单机还是集群中使用都是可以有效的防止超卖的。
    大概的思路是由redis的setNX命令实现进行加锁,加锁之后实现单线程减库存,这也算是一种相对较好的解决方式。

    防止商品超卖的 3 个思路!

    3、思路3

    我在网上曾看到有人列举前面两种实现方式,这里重点说明下,单机锁和分布式锁是不推荐的!
    其实防超卖最终的目的是防止数据库的库存(goods_num)小于0。导致小于0的原因是多个线程在程序中计算库存,然后在赋值给数据库。这么多锁要解决的问题,其实一条sql就可以实现。

    update t_goods set goods_num=goods_num - 1 where goods_id=1 and goods_num>0
    

    如上所示。例如卖了id为1的商品1件。这时库存减一,重点是where条件中判断了goods_num>0。这样就间接的限制了只有库存在大于1的时候该sql才会减一。直接就防止了超卖的现象。
    其实这个时候应该就会有人抬杠了,这是电商场景呀,直接连接数据库压力很大的。其实这个时候就要在减库存之前进行友好的限流了。
    redis提供了几个命令:

    • incr——加

    • decr——减

    • incrby——阶梯加

    • decrby——阶梯减
      这几个都是原子操作,并且在执行成功之后会返回结果。例如:

      redis> SET failure_times 10 OK redis> DECR failure_times (integer) 9

    这样如果有场景数据库减库存压力太大,可以双重判断,商品开卖之前,redis缓存商品的库存,先通过DECR减少redis库存,再减少数据库库存,当redis库存已经为0的时候,就没有必要再减少数据库的数据了。

    防止商品超卖的 3 个思路!

    总结

    如上便是我的想法,如果您有更好的解决方式,欢迎点评。


    起源地下载网 » 防止商品超卖的 3 个思路!

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元