库存设计:设置锁定库存和总库存,当用户下单未支付时锁定库存,支付成功时释放锁定库存并扣减总库存,当30分钟用户还未支付,此时释放锁定库存不扣减总库存。

一、库存超发原因:

下单流程:

当库存为1时,两个用户同时下单,查询库存时都有库存,都通过了库存数量校验,下单成功库存为-1。

二、解决方案:

(1)悲观锁
实现方式:查询时添加更新锁。

实现原理:使当前线程持有数据库记录行更新锁,其它线程被挂起,直到当前线程执行完释放锁,其他线程才能获取行更新锁,这样就防止了超发现象。

select stock from t_stock where id=1 for update

(2)乐观锁

实现方式:添加版本号。

实现原理:先获取当前版本号,执行完业务流程进行库存更新时,判断当前线程持有的版本号是否与数据库中的版本号相同,如一致则更新库存并增加版本号。乐观锁是一种不会阻塞其它线程并发的机制,它不会使用数据库的锁进行实现

缺陷:库存充足,并发的用户无法下单

解决方法:

乐观锁重入机制:

1)使用时间戳执行重入,比如在100毫秒内重复执行。当因为版本号更行失败后,会尝试重新下单,但是会进行时间戳判断,如果在100毫秒内,就继续,否则就判定失败。

2)限制重复次数执行重入

(3)redis使用lua脚本实现

实现原理:lua语言的原子性

-- 获取当前库存
local stock = tonumber(redis.call('hget', productId, 'stock'))-- 如果购买量小于库存,返回0
if stock < quantity then return 0 end-- 减少库存
stock = stock - 1-- 保存当前库存
redis.call('hset', productId, 'stock', tostring(stock))-- 返回成功
return 1

使用redis实现代码:

@Autowired
private RedisTemplate redisTemplate;//lua脚本
String script = "local stock = tonumber(redis.call('hget', 'product', KEYS[1]) \n"+"if stock < ARGV[1] then return 0 end \n"+"stock = stock - 1 \n"+"redis.call('hset', 'product', KEYS[1], tostring(stock)) \n"+"return 1 \n";//在缓存Lua脚本后,使用该变量保存Redis返回的32位的SHAl编码,使用它去执行缓存的Lua脚本
String  shal  =  null ;@Override
public Long deductionStockByRedis(Integer productId, Integer qunatity )  {Long  result  =  null ;//获取底层Redis操作对象Jedis jedis = (Jedis)redisTemplate.getConnectionFactory().getConnection().getNativeConnection();Integer result = null;try  {//如果脚本没有加载过,那么进行加载,这样就会返回一个shal编码if  (shal == null )shal =jedis.scriptLoad(script) ;//执行脚本,返回结果List<String> key= new ArrayList<String>();key.add(productId.toString());List<String> avge = new ArrayList<String>();avge.add(qunatity.toString());result = (Integer)jedis.evalsha(shal, key, avge );   }finally{//确保jedisl顺利关闭if  (jedis  !=  null  &&  jedis . isConnected (}}  {jedis . close(} ;}return result;}

(4)根据数据库更新时会自动加上行级锁来实现防止超发

<update id="lockStock" parameterType="com.macro.mall.request.CartPromotionItem">UPDATE pms_sku_stockSETlock_stock = CASE id <foreach collection="cartPromotionItemList" item="promotionItem">WHEN #{promotionItem.productSkuId} THEN lock_stock + #{promotionItem.quantity} + #{promotionItem.restrictQuantity}</foreach>ENDWHERE( (stock -lock_stock) >0 )AND<![CDATA[(stock-lock_stock) >=]]> CASE id <foreach collection="cartPromotionItemList" item="promotionItem">WHEN #{promotionItem.productSkuId} THEN (#{promotionItem.quantity} + #{promotionItem.restrictQuantity})</foreach>ENDAND id IN<foreach collection="cartPromotionItemList" item="promotionItem" separator="," open="(" close=")">#{promotionItem.productSkuId}</foreach></update>

高并发引起的库存超发解决方案相关推荐

  1. 高并发下防止库存超卖解决方案

    一.概述 目前网上关于防止库存超卖,我没找到可以支持一次购买多件的,都是基于一次只能购买一件做的秒杀方案,但是实际场景中,一般秒杀活动都是支持1-5件的,因此为了补缺,写了此文,方便自己之后使用. 二 ...

  2. mysql处理高并发,防止库存超卖

    参考:http://blog.csdn.net/caomiao2006/article/details/38568825 今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年 ...

  3. mysql版本号超买_MySQL处理高并发,防止库存超卖

    今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...

  4. 转 mysql处理高并发,防止库存超卖

    今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...

  5. mysql 高并发 优惠券_转 mysql处理高并发,防止库存超卖

    今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...

  6. 多线程与高并发基础一(超发--多线程悲观锁,乐观锁、类数据库悲观锁乐观锁)

    PS:看完文章后对自己以前所做过的并发和锁机制有了深入原理的了解. 知其然和知其所以然! 遂以记之! 关键词: 线程,同步,单例,高并发,高访问,死锁 一.大规模并发带来的挑战 在过去的工作中,我曾经 ...

  7. mysql 高并发扣除库存_【并发】mysql处理高并发,防止库存超卖

    先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购 一个商品.然而,作为活动商品,库存肯定是很有限的,如何 ...

  8. Java实现库存防超卖_高并发场景-订单库存防止超卖

    背景 在电商系统中买商品过程,先加入购物车,然后选中商品,点击结算,即会进入待支付状态,后续支付. 过程需要检验库存是否足够,保证库存不被超卖. 场景一:买家需要购买数量可以多件 场景二:秒杀活动,到 ...

  9. Redis高并发场景下秒杀超卖解决

    目录 1 什么是秒杀 2 为什么要防止超卖 3 单体架构常规秒杀 3.1 常规减库存代码 3.2 模拟高并发 3.3 超卖现象 3.4 分析原因 4 简单实现悲观乐观锁解决单体架构超卖 4.1 悲观锁 ...

最新文章

  1. 艺考可以报考清华的计算机系吗,考中传的人太多?艺考生或许可以考虑一下清华、浙大...
  2. Linux下的编译(环境是centos6.8 gcc 4.4.7)
  3. 网络营销外包——网络营销外包新手如何理解优化对网络营销的重要性?
  4. CSS3 Media Queries详细介绍和使用实例
  5. Redhat、CentOS进单用户模式进行维护
  6. Vue Vuex todo举例
  7. python遍历文件内容_Python四种逐行读取文件内容的方法
  8. java web 服务器环境搭建之jdk安装
  9. iOS iphone屏幕分析(岂止而大)
  10. Java学习之文件操作
  11. 给php添加标题的代码,纯代码给WP网站的分类和Tag页面添加自定义标题
  12. 学 Win32 汇编[6]: 伪指令 DUP 与数组
  13. Redis实战(十三)Redis的三种集群方式
  14. OpenLayers使用symbolizers样式特征
  15. sdi线缆标准_影片创作与未来标准监看——监视器DP-V2421使用手记
  16. UE4打包并加载Pak-Windows/iOS/Android不同平台Editor/Runtime不同运行模式兼容
  17. sqlplus登录指定服务器,sqlplus 指定数据库
  18. android动态壁纸的制作教程,巧用Windows自带工具,简易制作动态壁纸教程
  19. 深度学习学习笔记——keras中的verbose
  20. linux下如何使用命令连接wifi

热门文章

  1. piczoom兼容性问题_浏览器不兼容原因及解决方案
  2. CentOS7 安装宝塔+安全狗
  3. 【庖丁解牛】图像处理库: 解决WeCenter至少需要有GD图像处理库才能正常运行
  4. python列表内数字怎么求和_python怎么把列表的值相加
  5. 错误 4 error C2039: “Sleep”: 不是“boost::this_thread”的成员
  6. 码农日常生活之Git Gitlab Gitk
  7. 微软账号被暂时停用咋办_无需惊慌!微软漏洞数月后再被“预警” 打补丁即可防御...
  8. windows初始化所有设置
  9. 2023年2月中国数据库排行榜:OTO新格局持续三月,人大金仓、AnalyticDB排名创新高
  10. pdf转换成jpg格式的转换方法