高并发秒杀场景下,基于Redis、LUA防止商品超卖
liuian 2024-12-25 14:00 69 浏览
关联阅读
与超卖问题对应的是商品热Key的解决方案:
高并发情况下,库存扣减、查询等操作就不要考虑用数据库了,Redis是比较常用的解决方案,主要是基于Redis的高并发、原子性的特点。
防止用户重复提交购买
如果前端的“购买”按钮没有置灰,用户可能会反复点击,或者有的用户用软件去刷单,可以使用限流、分布式锁等方式来限制用户的请求。
以分布式锁为例,可以使用“用户ID+排序后的商品ID:购买数量”为Key,例如userId999-spuId111:10-spuId222:10。
但如果用户发N个请求,每个请求的商品ID、购买数量都不一样,或者用户在多客户端发起对不同商品的购买,则这种锁就被绕过。
如果要求严格的话,可以直接锁用户,这样会使客户无法在多客户端进行购买。
按照业务要求进行处理吧。
防止超卖
分两种情况:
一、一次只允许购买一个
使用Redis的List。假设有10个库存,则list插入10个1,购买的时候,使用lpop或rpop取出一个元素,如果为1,则说明有货,执行购买流程,如果为nil说明无货,直接返回。
如果要求一个用户只能购买一次,则需要搭配Redis的Set,通过sadd插入用户ID,如果用户没有购买记录,则sadd返回值为1,否则为0。
二、允许购买多个
步骤如下:
1、先查库存,如果库存-购买数<0,则说明用户购买的数量大于库存,返回失败。否则执行扣减库存流程。
2、使用"decrby key 购买数",扣减库存,返回成功。
按照上述步骤会出现以下情况:
A、用户甲购买时,步骤1,2之间无其他操作,顺利抢购成功,返回的库存数必>=0。
B、用户甲购买时,步骤1,2之间,用户乙抢先扣了库存,导致用户甲再扣库存时,超卖了。
流程示意:
甲查询库存10,购买数5,通过-->
乙查询库存10,购买数6,通过-->
乙扣减库存数6,现有库存4-->
甲扣减库存数5,现有库存数-1,导致超卖。
所以AB两个步骤的操作万不可使用程序来处理,而应该使用LUA脚本,Redis保证了执行LUA脚本的原子性。代码如下:
--商品Key
local key = KEYS[1]
--购买数
local val = ARGV[1]
--现有总库存
local stock = redis.call("GET", key)
if (tonumber(stock)<=0)
then
--没有库存
print("没有库存")
return -1
else
--获取扣减后的总库存=总库存-购买数
local decrstock=redis.call("DECRBY", key, val)
if(tonumber(decrstock)>=0)
then
--扣减购买数后没有超卖,返回现库存
print("没有超卖,现有库存数"..decrstock)
return decrstock
else
--超卖了,把扣减的再加回去
redis.call("INCRBY", key, val)
print("超卖了,现有库存"..stock.."不够购买数"..val)
return -2
end
end因为我也没系统学过LUA语言,今天也是一边查资料一边写脚本,有几个地方记录一下:
1、Redis存的是数字,但取出来的是String,所以比较数字的时候用tonumber()?转一下。
2、print的连接符是..不是+
测试
我使用的是dockey,先把lua脚本上传至docker
docker cp /本地目录/decrby.lua 容器ID:/data先预热商品库存,库存数100
set spu 100执行扣减脚本,购买数50,结果应返回50,再get应该是50
redis-cli --eval decrby.lua spu , 50注意:key、value两处,前后要有空格。
结果如下:
执行扣减脚本,购买数51,结果应返回-2,再get应该还是50
执行扣减脚本,购买数50,结果应返回0,再get应该为0
执行扣减脚本,购买数5,结果应返回-1,再get应该为0
在实际工作中,如果我们使用Spring Boot的RedisTemplate,这段脚本可以声明为静态String。
相关推荐
- wifi密码破解器电脑版(wifi密码破解工具电脑版)
-
肯定不是万能钥匙这种“破解”wifi的东西。不是一两次见到把万能钥匙当做破解wifi用的人了,但实际上那玩意就是个分享wifi的软件。你连上一个wifi,密码就会被分享到云端(可以不分享),别...
- 手机临时文件夹在哪个位置(手机临时文件夹在哪个位置找)
-
1.手机文件临时文件是指在手机使用过程中产生的临时文件。2.手机应用程序在运行时需要产生一些临时文件,如缓存文件、日志文件、临时下载文件等,这些文件可以提高应用程序的运行效率和用户体验。但是,这些...
- 安卓10系统下载(安卓10 下载)
-
方法及步骤: 其实使用安卓车机下载歌曲的方法十分的简单,具体操作步骤和安卓手机一模一样。 首先我们需要在车机的应用商店上,下载一个音乐播放器,例如网易云音乐或者QQ音乐等。 下载完成后点击进入...
- 华硕人工客服24小时吗(华硕售后人工客服)
-
华硕服务中心广东省惠州市惠东县城平深路(创富斜对面)惠东同心电脑城1L11(1.3km)笔记本电脑,平板电脑华硕服务中心广东省惠州市惠东县平山镇同心电脑城1F26(1.3km)笔记本电脑,平...
- 电脑音量小喇叭不见了(电脑声音喇叭图标不见了怎么办)
-
如果您电脑上的小喇叭(扬声器)不见了,可以尝试以下方法找回:1.检查设备管理器:在Windows下,右键点击“我的电脑”(或此电脑)->点击“属性”->点击“设备管理器”,查看“声音、视...
- 腾达路由器手机设置教程(腾达路由器手机设置教程视频)
-
用手机设置腾达路由器的方法如下:1在手机上打开浏览器,输入路由器背面的管理IP和用户及对应的密码2一般第一次打开,默认会跳出设置向导,准备好宽带用户名和密码,3按向导提示输入相应内容4在无线设置的安全...
- 自配电脑配置推荐(自配电脑配置推荐百度)
-
首先,像这类软件最低要求不高。最高没上限。纯粹看你的工程量大小。CPU有双核,内存有4G,就可以运行。但是实际体验肯定比较差,卡是肯德。渲染时间也会超长,一个小作品渲染几小时是正常的。稍微大点的工程也...
- 2025年平板性价比排行(2020年值得买的平板)
-
推荐台电P30S好。 基本配置:10.1英寸IPS广视角屏幕,1280*800分辨率,16:10的黄金显示比例,K9高压独立功放,支持3.5mm耳麦接口,联发科MT8183八核处理器,4GB...
- 2020显卡天梯图10月(2020显卡天梯图极速空间)
-
排行球队名称积分已赛胜平负进球失球净胜球 1?诺维奇城974629107753639 2?沃特福德91462710...
-
- 笔记本电脑无线网络连接(笔记本电脑无线网络连接不上怎么办)
-
一、笔记本电脑怎么连接wifi---win7系统笔记本连接wifi1、要先创建无线网络连接,将鼠标移到Win7的开始菜单,然后点击“控制面板”。2、然后点击“网络和Internet”。3、再打开“网络和共享中心”,这是Win7系统必有的功...
-
2025-12-22 05:55 liuian
- wind数据库(wind数据库官网)
-
先购买wind数据库,安装好wind取得使用权后,按照wind所给提示,输入账户和密码可使用wind数据库。Wind资讯金融终端是一个集实时行情、资料查询、数据浏览、研究分析、新闻资讯为一体的金融数据...
- 如何关闭360家庭防火墙(如果关闭360家庭防火墙)
-
关闭方法如下:1.打开手机360主界面之后,点击“安全防护中心”。2.点击第三列“入口防护”下方的“查看状态”按钮。3.在列出的功能项中找到“局域网防护”,直接点击后面的“关闭”按钮,关闭所有的“局域...
- 笔记本电脑型号配置怎么看(怎么查自己电脑的型号)
-
查电脑的配置和型号方法:方法一:1、右键单击“此电脑”,点击属性2、这里可以看到操作系统,CPU等大致信息3、点击设备管理器4、这里可以查看具体硬件的详细信方法二:1、首先打开电脑上的“控制面板”2、...
- pscs6序列号是什么
-
AdobePhotoshopCS6就二个版本(测试版和正式版)1、AdobePhotoshopCS6是AdobePhotoshop的第13代,是一个较为重大的版本更新。2、Photoshop在前几...
- 一周热门
- 最近发表
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)
- mysql刷新权限 (34)
