当前位置: 首页 > news >正文

通过Redis增减库存避坑

问题
先执行get获取值,判断符合条件再执行incr、decr操作。在临界缓存失效的情况下,会默认赋值当前key为永不过期的0,再执行加减法,导致程序异常。

推荐解决方案
1、限制接口频率:先incr,执行后值为1,说明是第一次执行,需要额外设置过期时间,再判断是否超过当前接口频率限制(注意上述步骤不可调换顺序)

2、使用lua脚本完整提交一次操作,脚本中的key可以保证一致。以加减库存为例,先查询key存在的情况下,再进行库存变更,如果不存在无需处理,等待下次缓存加载即为最新的值


问题描述

场景1:我们缓存了一个商品的库存,过期时间为5分钟,根据用户的购买和取消执行 incr、decr 操作。代码通常会这样来编写:

		// 库存存在则加一if(redisService.get(prefix, key, Integer.class) != null){redisService.incr(prefix, key);}

场景2:对访问频次进行限流,我们可以通过redis简单实现:

        // 首先获取当前访问频次Integer count = redisService.get(prefix, key, Integer.class);// 如果频次为空,则设置访问次数为1if (count == null) {redisService.set(prefix, key, 1);} else if (count < checkFrequencyCount) {// 如果频次小于限制,则设置访问次数加1redisService.incr(prefix, key);} else {// 如果频次超过限制,则限流throw new AppException("访问频次过高,请稍候再试");}

两种场景编码看似都没有问题,但实际运行中却发现redis中有一些key变成了永不过期的key,而且值不正确。

原因是: 因为redis的incr操作,当key不存在时, 会生成这个key并将值初始化为0, 并且默认设置key的有效时间为永久。


解决方案

1.优化Java代码,例如场景2。不论这个key是否存在都先加一,然后判断其过期时间是否为永不过期,如果是永不过期则说明是新生成的key,给它设置过期时间即可,如果非永不过期则无需操作。最后再判断一下是否值已经大于访问频次了,是则限流。

		long count = redisService.incr(prefix, key);// 判断必须放在后面,否则key没有过期时间永远无法清除long expire = redisService.ttl(prefix, key);if (expire == -1) {redisService.setExpire(prefix, key, accessExpireSecond);}if (count > checkFrequencyCount) {throw new AppException("访问频次过高,请稍候再试");}

2.使用lua脚本执行,保证原子性。

脚本updateStore.lua

--- 获取key
local key = KEYS[1]
--- 获取参数:incr、decr
local action = ARGV[1]
--- 如果key存在,再执行增加或减少的操作
if redis.call('exists', key) == 1 
then redis.call(action, key)return true
end 
return false

配置LuaConfiguration.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;@Configuration
public class LuaConfiguration {@Bean(name = "update")public DefaultRedisScript<Boolean> redisScript() {DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("luascript/updateStore.lua")));redisScript.setResultType(Boolean.class);return redisScript;}
}

使用方法:

    @Resource(name = "update")private DefaultRedisScript<Boolean> redisScript;@Resourceprivate StringRedisTemplate stringRedisTemplate;// 执行脚本并传参Boolean result = stringRedisTemplate.execute(redisScript, Arrays.asList(stockPrefix.getPrefix() + key), "incr");

相关文章:

通过Redis增减库存避坑

问题&#xff1a; 先执行get获取值&#xff0c;判断符合条件再执行incr、decr操作。在临界缓存失效的情况下&#xff0c;会默认赋值当前key为永不过期的0&#xff0c;再执行加减法&#xff0c;导致程序异常。 推荐解决方案&#xff1a; 1、限制接口频率&#xff1a;先incr&…...

Windows系统搭建Elasticsearch引擎结合内网穿透实现远程连接查询数据

文章目录 系统环境1. Windows 安装Elasticsearch2. 本地访问Elasticsearch3. Windows 安装 Cpolar4. 创建Elasticsearch公网访问地址5. 远程访问Elasticsearch6. 设置固定二级子域名 Elasticsearch是一个基于Lucene库的分布式搜索和分析引擎&#xff0c;它提供了一个分布式、多…...

Java爬虫使用JSoup获取静态资源图片

import org.jsoup.Connection; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.FileOutputStream;/*** 获取静态图片*/public class ImageDownloader {public static void main…...

LeetCode 2433.找出前缀异或的原始数组

给你一个长度为 n 的 整数 数组 pref 。找出并返回满足下述条件且长度为 n 的数组 arr &#xff1a; pref[i] arr[0] ^ arr[1] ^ … ^ arr[i]. 注意 ^ 表示 按位异或&#xff08;bitwise-xor&#xff09;运算。 可以证明答案是 唯一 的。 示例 1&#xff1a; 输入&#xf…...

C++面试:系统网络性能评估与优化

系统网络性能评估与优化是指对计算机系统中的网络部分进行评估分析&#xff0c;并采取一系列措施来提升网络性能的能力。在面试中&#xff0c;涉及这一主题的问题可能会围绕以下几个方面展开。 网络性能评估 基于网络延迟、带宽、吞吐量等指标对网络性能进行评估。使用工具&a…...

Java适配器模式 - 灵活应对不匹配的接口

Java适配器模式 - 灵活应对不匹配的接口 引言&#xff1a; 在软件开发中&#xff0c;我们经常遇到不同系统、库或框架之间的接口不兼容问题。为了解决这些问题&#xff0c;我们可以使用适配器模式。适配器模式是一种结构型设计模式&#xff0c;它允许不兼容的接口之间进行协作…...

[ai笔记12] chatGPT技术体系梳理+本质探寻

欢迎来到文思源想的ai空间&#xff0c;这是技术老兵重学ai以及成长思考的第12篇分享&#xff01; 这周时间看了两本书&#xff0c;一本是大神斯蒂芬沃尔弗拉姆学的《这就是ChatGPT》,另外一本则是腾讯云生态解决方案高级架构师宋立恒所写的《AI制胜机器学习极简入门》&#xf…...

Elasticsearch:使用 ELSER v2 进行语义搜索

在我之前的文章 “Elasticsearch&#xff1a;使用 ELSER 进行语义搜索”&#xff0c;我们展示了如何使用 ELESR v1 来进行语义搜索。在使用 ELSER 之前&#xff0c;我们必须注意的是&#xff1a; 重要&#xff1a;虽然 ELSER V2 已正式发布&#xff0c;但 ELSER V1 仍处于 [预览…...

智慧农业之智能物流

智慧物流属于农业生产环节中的重要节点,上游为农业生产环节,下游为销售与商贸环节,因此,通过联通生产与销售环节,通过合理调配物流过程,可以实现对于农产品的快速运输与销售,减少中间环节中的无效损耗,从而实现增收节支,实实在在地解决了农产品利润偏低的问题。 生产…...

Redis主从、哨兵、Redis Cluster集群架构

Redis主从、哨兵、Redis Cluster集群架构 Redis主从架构 Redis主从架构搭建 主从搭建的问题 如果同步数据失败&#xff0c;查看log日志报错无法连接&#xff0c;检查是否端口未开放出现”Error reply to PING from master:...“日志&#xff0c;修改参数protected-mode no …...

Javascript 运算符、流程控制语句和数组

【三】运算符 【1】算数运算符 &#xff08;1&#xff09;分类 加减乘除&#xff1a;*/取余&#xff1a;%和python不一样的点&#xff1a;没有取整// &#xff08;2&#xff09;特殊的点 只要NaN参与运算得到的结果也是NaNnull转换成0&#xff0c;undefined转换成NaN 【2…...

电机驱动死区时间

电机驱动死区时间 电机驱动死区时间死区时间&#xff08;Dead Time&#xff09;自己话补充说明 电机驱动死区时间 电机驱动死区时间一般在几纳秒到几微秒之间&#xff0c;具体长度取决于所使用的电子器件。 一、什么是电机驱动死区时间&#xff1f; 电机驱动死区时间指的是在电…...

图像的压缩感知的MATLAB实现(第3种方案)

前面介绍了两种不同的压缩感知实现&#xff1a; 图像压缩感知的MATLAB实现&#xff08;OMP&#xff09; 压缩感知的图像仿真&#xff08;MATLAB源代码&#xff09; 上述两种方法还存在着“速度慢、精度低”等不足。 本篇介绍一种新的方法。 压缩感知&#xff08;Compressed S…...

高温应用中GaN HEMT大信号建模的ASM-HEMT

来源&#xff1a;An ASM-HEMT for Large-Signal Modeling of GaN HEMTs in High-Temperature Applications&#xff08;JEDS 23年&#xff09; 摘要 本文报道了一种用于模拟高温环境下氮化镓高电子迁移率晶体管&#xff08;GaN HEMT&#xff09;的温度依赖性ASM-HEMT模型。我…...

文件上传---->生僻字解析漏洞

现在的现实生活中&#xff0c;存在文件上传的点&#xff0c;基本上都是白名单判断&#xff08;很少黑名单了&#xff09; 对于白名单&#xff0c;我们有截断&#xff0c;图片马&#xff0c;二次渲染&#xff0c;服务器解析漏洞这些&#xff0c;于是今天我就来补充一种在upload…...

Ubuntu中Python3找不到_sqlite3模块

今天跑一个代码&#xff0c;出现了一个找不到sqlite3模块的错误&#xff0c;错误如下: from _sqlite3 import * ModuleNotFoundError: No module named _sqlite3 网上查资料说&#xff0c;因为python3没有自带sqlite3相关方面的支持&#xff0c;要自己先安装然后再重新编译Py…...

HarmonyOS4.0系统性深入开发37 改善布局性能

改善布局性能 Flex为采用弹性布局的容器。容器内部的所有子元素&#xff0c;会自动参与弹性布局。子元素默认沿主轴排列&#xff0c;子元素在主轴方向的尺寸称为主轴尺寸。 在单行布局场景下&#xff0c;容器里子组件的主轴尺寸长度总和可能存在不等于容器主轴尺寸长度的情况…...

Internet协议

文章目录 Internet协议网络层协议IPV4协议IP地址&#xff1a;IPv4数据报格式IP数据报的封装和分片 Internet路由协议路由信息协议RIP开放最短路径优先协议OSPF外部网关协议BGP组播协议PIM和MOSPF ARP和RARPARP协议&#xff1a;RARP协议&#xff1a; Internet控制报文协议ICMPIP…...

深度学习基础(一)神经网络基本原理

之前的章节我们初步介绍了机器学习相关基础知识&#xff0c;目录如下&#xff1a; 机器学习基础&#xff08;一&#xff09;理解机器学习的本质-CSDN博客 机器学习基础&#xff08;二&#xff09;监督与非监督学习-CSDN博客 机器学习基础&#xff08;四&#xff09;非监督学…...

2024年2月22日 - mis

rootyy3568-alip:/sys# ls /sys/class/gpio/gpio* -F /sys/class/gpio/gpio114 /sys/class/gpio/gpiochip511 /sys/class/gpio/gpiochip0 /sys/class/gpio/gpiochip64 /sys/class/gpio/gpiochip128 /sys/class/gpio/gpiochip96 /sys/class/gpio/gpiochip32符号表示该文…...

如何用EuRoC数据集快速搭建VIO算法测试环境(附Python代码示例)

如何用EuRoC数据集高效构建VIO算法验证平台&#xff08;附Python实战&#xff09; 当我们需要验证视觉惯性里程计&#xff08;VIO&#xff09;算法时&#xff0c;一个高质量的数据集就像实验室里的精密仪器。EuRoC数据集正是这样一套"标准量具"&#xff0c;它由微型飞…...

5分钟搞定Netdata监控面板汉化:最新GitHub汉化包一键安装教程

Netdata监控面板极速汉化指南&#xff1a;从零到精通的完整解决方案 对于国内开发者而言&#xff0c;英文界面始终是技术工具使用中的一道隐形门槛。Netdata作为一款功能强大的实时监控工具&#xff0c;其全英文的仪表盘让不少运维人员望而却步。本文将带你彻底解决这一痛点&am…...

VR视频转换:让3D内容在普通设备焕发新生的开源方案

VR视频转换&#xff1a;让3D内容在普通设备焕发新生的开源方案 【免费下载链接】VR-reversal VR-Reversal - Player for conversion of 3D video to 2D with optional saving of head tracking data and rendering out of 2D copies. 项目地址: https://gitcode.com/gh_mirro…...

Minitab单因子方差分析实战:从数据导入到结果解读全流程(附油漆硬度案例)

Minitab单因子方差分析实战&#xff1a;从数据导入到结果解读全流程&#xff08;附油漆硬度案例&#xff09; 在工业质量控制和科研实验中&#xff0c;我们常常需要比较不同组别间的均值差异是否具有统计学意义。单因子方差分析&#xff08;One-Way ANOVA&#xff09;正是解决这…...

NoFences终极指南:3步打造零杂乱的高效Windows桌面

NoFences终极指南&#xff1a;3步打造零杂乱的高效Windows桌面 【免费下载链接】NoFences &#x1f6a7; Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences 还在为Windows桌面上的图标海洋而烦恼吗&#xff1f;NoFences作…...

用快马平台十分钟搭建你的第一个zotero式文献管理web原型

今天想和大家分享一个超实用的开发经验&#xff1a;如何用InsCode(快马)平台快速搭建文献管理系统的web原型。作为一个经常需要整理论文的研究狗&#xff0c;zotero这类工具简直是刚需&#xff0c;但有时候我们想验证一些定制化功能的想法&#xff0c;从零开发又太耗时。下面我…...

如何通过铜钟音乐重拾纯粹听歌的乐趣:一个零干扰的Web音乐解决方案

如何通过铜钟音乐重拾纯粹听歌的乐趣&#xff1a;一个零干扰的Web音乐解决方案 【免费下载链接】tonzhon-music 铜钟 (Tonzhon.com): 免费听歌; 没有直播, 社交, 广告, 干扰; 简洁纯粹, 资源丰富, 体验独特&#xff01;(密码重置功能已回归) 项目地址: https://gitcode.com/G…...

为什么92%的FastAPI AI服务仍在用阻塞式响应?(深度剖析async def vs sync def在LLM流式场景下的内存泄漏与协程死锁)

第一章&#xff1a;FastAPI 2.0异步AI流式响应的核心价值与演进脉络在大模型服务规模化部署的背景下&#xff0c;传统同步HTTP响应已难以满足低延迟、高吞吐、用户体验敏感的AI交互场景。FastAPI 2.0通过深度整合Python 3.11原生异步运行时、优化ASGI中间件栈及重构StreamingRe…...

从Sketchfab下载的glTF模型怎么用?手把手教你用Assimp 5.3.1在Visual Studio 2022里解析《蔚蓝档案》角色数据

从Sketchfab下载的glTF模型实战解析&#xff1a;用Assimp 5.3.1提取《蔚蓝档案》角色数据 当你在Sketchfab上发现一个精美的《蔚蓝档案》角色模型&#xff0c;下载glTF格式文件后&#xff0c;接下来该怎么办&#xff1f;本文将带你从零开始&#xff0c;使用Assimp 5.3.1库在Vi…...

开源协作机器人的架构革命:OpenArm如何重构机器人研发范式

开源协作机器人的架构革命&#xff1a;OpenArm如何重构机器人研发范式 【免费下载链接】openarm OpenArm v0.1 项目地址: https://gitcode.com/GitHub_Trending/op/openarm 当传统工业机械臂的封闭生态成为技术创新的桎梏&#xff0c;当高昂的硬件成本将学术研究拒之门外…...