使用乐观锁解决电商中商品超卖的问题

TuskueNeko TuskueNeko     2022-11-29     447

关键词:

电商项目中下单是要减库存的,但是当多个用户同时请求时会产生并发,导致多个线程同时减库存,库存可能变为负数,在这里我记一下一个简单的防止超卖的方法。

 

JAVA代码:
 

private ResultDTO<Object> checkAndUpdateInventory(SampleInventoryDTO dto, int index) throws InterruptedException 
        if (index > 15) 
        	throw new BusinessException("同时操作人数过多,请稍后再试!", DataContract.SAMPLE_INVENTORY_UPDATE_TOOMUCH_CODE);
        
        if (index >= 3) 
            //如果三次以上都没有更新成功则睡眠100毫秒
            Thread.sleep(100);
        
        //根据商品ID查询库存
        Integer inventory = productDao.queryInventory(dto.getProductNo());
        ProductVO vo = new ProductVO ();
        vo.setProductNo(dto.getProductNo());
        vo.setQuantity(dto.getQuantity());
        vo.setInventory(inventory);
        if (inventory >= dto.getQuantity()) 
                if (productDao.updateQuantityByVersion(vo) < 1) 
                    return checkAndUpdateInventory(dto, ++index);
                 else 
                    return ResponseUtil.generateSuccessDTO("修改库存成功.");
                
             else 
                return ResponseUtil.generateFaileDTO("商品库存不足!", DataContract.SAMPLE_INVENTORY_NOT_ENOUGH_CODE);
        

    

再贴上关键的SQL代码(productDao.updateQuantityByVersion() 的SQL):


	 UPDATE SAMPLE 
	 SET 
	 INVENTORY= INVENTORY - #quantity 
	 WHERE RECORD_NO=#sampleNo AND INVENTORY = #inventory AND INVENTORY >= #quantity

整体思路就是在更新库存之前先查询一下库存,判断是不是足够且有没有变动过,在执行更新SQL库存时如果库存不等于查出来的库存,则表示有其它线程修改了库存,因此进入递归重新查询库存,直到更新库存SQL执行成功,这里使用了quantity库存数量代替了乐观锁的版本号,个人感觉相比较排它锁的性能慢,和队列的麻烦,这个方法最简单,当然,要是项目并发很高的话还是推荐用列队比较好。

 

避免商品超卖的4种方案(代码片段)

...个条件,只更改商品库存大于0的商品的库存,当时我们使用ab进行压力测试,当并发超过500,访问量超过2000时,还是会出现超卖现象。publicfunctionbuyOne()$shop=Shop::find(1);if($shop->number>0)DB::update("updateshopsetnumber=number-1whereid=1");第... 查看详情

深入了解分布式锁导学篇(代码片段)

...处理。学习成果可以一定程度上基本的分布式锁的原理和使用有着较为深入的理解熟练使用redis和zookeeper进行分布式锁的实现并且对高并发下超卖问题有着深入理解。文章重点该文章主要以以下几大方面解决超卖问题的解决方案&... 查看详情

电商仓储控制超卖的策略

...一个是仓内的管理,另一个是仓库WMS系统和店铺ERP系统及电商平台的商家后台。   1)仓内管理:这点不详细展开,仓库专业人员的专业能力是应该相信的,只是简单说几点:   关于库存变动:商品入仓后,因各种原... 查看详情

数据库中常用的悲观锁和乐观锁

...量,此时,如果都同时购买就使库存不够,这时候就需要使用,行锁,只让某一个线程购买,其他访问线程就是搁置着,这个时候就会使访问网站瘫痪的可能。乐观锁:就是使用redis,同时有一万个用户访问,乐观的认为不会存... 查看详情

解决redis秒杀超卖的问题

我们再使用redis做秒杀程序的时候,解决超卖问题,是重中之重。以下是一个思路。  用上述思路去做的话,我们再用户点击秒杀的时候,只需要检测,kucun_count中是否能pop出数据,如果能pop出来则证明还有库存,且秒杀成功... 查看详情

悲观锁乐观锁(代码片段)

悲观锁与乐观锁是人们定义出来的概念,你可以理解为一种思想,是处理并发资源的常用手段。其与mysql中提供的锁机制(表锁,行锁,排他锁,共享锁)并不同,后者可以成为前者的实现手段。悲观锁顾名思义,就是对于数据的... 查看详情

redis中的乐观锁和悲观锁

...,只要key不变就代表不会出问题。redis中的事务multi默认使用乐观锁,这将会导致一个问题:在秒杀这种高并发环境下,容易造成超卖问题。如,在一件商品只剩一件时,这时A用户开启事务只准备抢购,而就在A完成事务之前,B... 查看详情

使用分布式锁时考虑哪些问题

工作中经常会遇到争抢共享资源的场景,比如用户抢购秒杀商品,如果不对商品库存进行保护,可能会造成超卖的情况。超卖现象在售卖火车票的场景下更加明显,两个人购买到同一天同一辆列车,相同座位的情况是不允许出现... 查看详情

使用mysql悲观锁解决商品超卖问题(代码片段)

...锁机制,也无法保证外部系统不会修改数据)。使用场景举例:以MySQLInnoDB为例商品goods表,假设商品的id为1,购买数量为1,status为1表示上架中,2表示下架。现在用户购买此商品,在不是高并发的... 查看详情

java秒杀系统解决方案

...牛云等。2、点击秒杀按钮后,记得将按钮禁用。3、使用验证码恶意防刷。4、商品的详情页可以使用页面静态化技术提高响应速度  有两种方式,一种是使用nginx对页面进行缓存配置,一种是直接利用浏览器端缓存&... 查看详情

利用乐观锁及redis解决电商秒杀高并发基本逻辑

...问题方法很多,如悲观锁,消息队列等……利用乐观锁及redis解决秒杀高并发基本逻辑//初始化redis$redis=newRedis();//设置键值,起到监视作用 执行事务之前,判断被修改,回滚$redis->watch(‘sales‘);//获取销量$sales=$redis... 查看详情

简历上写的电商,那请问redis如何实现库存扣减操作和防止被超卖?

...中的商品库存,抽奖系统中的奖品库存等。解决方案使用mysql数据库,使用一个字段来存储库存,每次扣减库存去更新这个字段。还是使用数据库,但是将库存分层多份存到多条记录里面,扣减库存的时候路由... 查看详情

京东一面:redis如何实现库存扣减操作?如何防止商品被超卖?

...系统中的商品库存,抽奖系统中的奖品库存等。解决方案使用mysql数据库,使用一个字段来存储库存,每次扣减库存去更新这个字段。还是使用数据库,但是将库存分层多份存 查看详情

订单并发商品超卖问题解决(代码片段)

...ii\\db\\Exception*/publicfunctionactionIndex()$redis=Yii::$app->redis;//使用redis做一些统计$redis->incr(‘total‘);//自增(记录一共成功进来了多少个请求 查看详情

深入理解jvm锁与分布式锁(代码片段)

...下图所示。这里,我也给出相应的代码片段吧。我们可以使用下面的代码片段来表示用户的下单操作,我这里将商品的库存信息保存在了Redis中。@RequestMapping("/submitOrder")publicStringsubmitOrder()intstock=Integer.parseInt(stringRedisTemplate.opsForV... 查看详情

秒杀系统防止库存超卖

...执行成功大型互联网不是这么玩的数据库有瓶颈第二种:使用redis分布式锁实现varresource="the-thing-we-are-locking-on 查看详情

悲观锁与乐观锁的一些使用(代码片段)

...多并发,是单线程操作,通过抢占时间片的方式来抢锁的使用权,把并发变成了串行。2425共享资源每次只给一个线程使用 查看详情

优惠卷秒杀系统设计全局唯一id生成,秒杀下单,分析解决库存超卖(乐观锁)实现一人一单秒杀业务(对用户id加锁)集群模式下并发问题(代码片段)

...生成订单并保存到tb_voucher_order这张表中,而订单表如果使用数据库自增ID就存在一些问题:场景分析:场景分析二:全局ID生成器,是一种在分布式系统下用来生成全局唯一ID的工具,一般要满足下列特性:为了增加ID的安全性,... 查看详情