高并发引起的库存超发解决方案
库存设计:设置锁定库存和总库存,当用户下单未支付时锁定库存,支付成功时释放锁定库存并扣减总库存,当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-5件的,因此为了补缺,写了此文,方便自己之后使用. 二 ...
- mysql处理高并发,防止库存超卖
参考:http://blog.csdn.net/caomiao2006/article/details/38568825 今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年 ...
- mysql版本号超买_MySQL处理高并发,防止库存超卖
今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...
- 转 mysql处理高并发,防止库存超卖
今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...
- mysql 高并发 优惠券_转 mysql处理高并发,防止库存超卖
今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...
- 多线程与高并发基础一(超发--多线程悲观锁,乐观锁、类数据库悲观锁乐观锁)
PS:看完文章后对自己以前所做过的并发和锁机制有了深入原理的了解. 知其然和知其所以然! 遂以记之! 关键词: 线程,同步,单例,高并发,高访问,死锁 一.大规模并发带来的挑战 在过去的工作中,我曾经 ...
- mysql 高并发扣除库存_【并发】mysql处理高并发,防止库存超卖
先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购 一个商品.然而,作为活动商品,库存肯定是很有限的,如何 ...
- Java实现库存防超卖_高并发场景-订单库存防止超卖
背景 在电商系统中买商品过程,先加入购物车,然后选中商品,点击结算,即会进入待支付状态,后续支付. 过程需要检验库存是否足够,保证库存不被超卖. 场景一:买家需要购买数量可以多件 场景二:秒杀活动,到 ...
- Redis高并发场景下秒杀超卖解决
目录 1 什么是秒杀 2 为什么要防止超卖 3 单体架构常规秒杀 3.1 常规减库存代码 3.2 模拟高并发 3.3 超卖现象 3.4 分析原因 4 简单实现悲观乐观锁解决单体架构超卖 4.1 悲观锁 ...
最新文章
- 艺考可以报考清华的计算机系吗,考中传的人太多?艺考生或许可以考虑一下清华、浙大...
- Linux下的编译(环境是centos6.8 gcc 4.4.7)
- 网络营销外包——网络营销外包新手如何理解优化对网络营销的重要性?
- CSS3 Media Queries详细介绍和使用实例
- Redhat、CentOS进单用户模式进行维护
- Vue Vuex todo举例
- python遍历文件内容_Python四种逐行读取文件内容的方法
- java web 服务器环境搭建之jdk安装
- iOS iphone屏幕分析(岂止而大)
- Java学习之文件操作
- 给php添加标题的代码,纯代码给WP网站的分类和Tag页面添加自定义标题
- 学 Win32 汇编[6]: 伪指令 DUP 与数组
- Redis实战(十三)Redis的三种集群方式
- OpenLayers使用symbolizers样式特征
- sdi线缆标准_影片创作与未来标准监看——监视器DP-V2421使用手记
- UE4打包并加载Pak-Windows/iOS/Android不同平台Editor/Runtime不同运行模式兼容
- sqlplus登录指定服务器,sqlplus 指定数据库
- android动态壁纸的制作教程,巧用Windows自带工具,简易制作动态壁纸教程
- 深度学习学习笔记——keras中的verbose
- linux下如何使用命令连接wifi
热门文章
- piczoom兼容性问题_浏览器不兼容原因及解决方案
- CentOS7 安装宝塔+安全狗
- 【庖丁解牛】图像处理库: 解决WeCenter至少需要有GD图像处理库才能正常运行
- python列表内数字怎么求和_python怎么把列表的值相加
- 错误	4	error C2039: “Sleep”: 不是“boost::this_thread”的成员
- 码农日常生活之Git Gitlab Gitk
- 微软账号被暂时停用咋办_无需惊慌!微软漏洞数月后再被“预警” 打补丁即可防御...
- windows初始化所有设置
- 2023年2月中国数据库排行榜:OTO新格局持续三月,人大金仓、AnalyticDB排名创新高
- pdf转换成jpg格式的转换方法