Redis使用lua脚本实现库存扣减

news2024/11/24 20:41:10

为什么使用Lua脚本为什么能合并多个原子操作?

这里参考官方文档地址:Scripting with Lua | Redis

Redis 保证Lua脚本的原子执行。在执行脚本时,所有服务器活动在其整个运行期间都被阻止。这些语义意味着脚本的所有效果要么尚未发生,要么已经发生。

脚本提供了几个在许多情况下都很有价值的属性。这些包括:

  • 通过在数据所在的地方执行逻辑来提供局部性。数据局部性减少了整体延迟并节省了网络资源。
  • 确保脚本原子执行的阻塞语义。
  • 启用 Redis 中缺少的或过于小众的简单功能的组合。

Lua 允许您在 Redis 中运行部分应用程序逻辑。这样的脚本可以跨多个键执行条件更新,可能以原子方式组合几种不同的数据类型。

命令行应用Lua

Redis Eval 命令使用 Lua 解释器执行脚本。

这里能帮我们实现 Redis 执行 Lua 脚本的命令有两个,一个是 EVAL,另一个是 EVALSHA。

redis Eval 命令基本语法如下:

EVAL script numkeys key [key ...] arg [arg ...] 

其中 EVAL 是命令,script 是我们 Lua 脚本的字符串形式,numkeys 是我们要传入的参数数量,key 是我们的入参,可以传入多个,arg 是额外的入参。

以下尝试演示脚本KEYS和ARGV运行时全局变量之间输入参数的分布:

redis> EVAL "return { KEYS[1], KEYS[2], ARGV[1], ARGV[2], ARGV[3] }" 2 key1 key2 arg1 arg2 arg3
1) "key1"
2) "key2"
3) "arg1"
4) "arg2"
5) "arg3"

但这种方式需要每次都传入 Lua 脚本字符串,不仅浪费网络开销,同时 Redis 需要每次重新编译 Lua 脚本,对于我们追求性能极限的系统来说,不是很完美。所以这里就要说到另一个命令 EVALSHA 了,原生语法如下:

EVALSHA sha1 numkeys key [key ...] arg [arg ...]

不同的是这里传入的不是脚本字符串,而是一个加密串 sha1。这个 sha1 是从哪来的呢?它是通过另一个命令 SCRIPT LOAD 返回的,该命令是预加载脚本用的。

从脚本与 Redis 交互

可以通过redis.call()或从 Lua 脚本调用 Redis 命令redis.pcall()。

两者几乎一模一样。两者都执行 Redis 命令及其提供的参数(如果这些参数表示格式正确的命令)。但是,这两个函数之间的区别在于处理运行时错误(例如语法错误)的方式。调用函数引发的错误redis.call()直接返回给执行它的客户端。相反,调用redis.pcall()函数时遇到的错误将返回到脚本的执行上下文,而不是进行可能的处理。

Java客户端应用Lua实例

注意Lua 脚本并不会自动帮你完成回滚操作,如果你的脚本逻辑中包含两步写操作,需要自己去做回滚。好在我们库存扣减的逻辑针对 Redis 的命令就两种,一个读一个写,并且写命令在最后,这样就不存在需要回滚的问题了。

以库存扣减核心操作为例,完成核心 Lua 脚本的编写。其主要实现的功能就是查询库存并判断库存是否充足,如果充足,则做相应的扣减操作,脚本内容如下:

-- 调用Redis的get指令,查询活动库存,其中KEYS[1]为传入的参数1,即库存key
local c_s = redis.call('get', KEYS[1])
-- 判断活动库存是否充足,其中KEYS[2]为传入的参数2,即当前抢购数量
if not c_s or tonumber(c_s) < tonumber(KEYS[2]) then
   return 0
end
-- 如果活动库存充足,则进行扣减操作。其中KEYS[2]为传入的参数2,即当前抢购数量
redis.call('decrby',KEYS[1], KEYS[2])

然后我们将 Lua 脚本转成字符串,并添加脚本预加载机制。

预加载可以有多种实现方式,一个是外部预加载好,生成了 sha1 然后配置到配置中心,这样 Java 代码从配置中心拉取最新 sha1 即可。

另一种方式是在服务启动时,来完成脚本的预加载,并生成单机全局变量 sha1。我们这里先采取第二种方式,代码结构如下图所示:

以上是将 Lua 脚本转成字符串形式,并通过 @PostConstruct 完成脚本的预加载。然后新增 EVALSHA 方法,如下图所示:

 

方法入参为活动商品库存 key 以及单次抢购数量,并在内部调用 Lua 脚本执行库存扣减操作。看起来是不是很简单?在写完底层核心方法之后,我们只需要在下单之前,调用该方法即可,具体如下图所示:

  

脚本缓存

到目前为止,我们已经使用EVAL命令来运行我们的脚本。

每当我们调用时EVAL,我们还会在请求中包含脚本的源代码。重复调用EVAL执行同一套参数化脚本,既浪费网络带宽,也对 Redis 有一定的开销。当然,节省网络和计算资源是关键,因此,Redis 为脚本提供了一种缓存机制。

您执行的每个脚本都EVAL存储在服务器保留的专用缓存中。缓存的内容由脚本的 SHA1 摘要总和组织,因此脚本的 SHA1 摘要总和在缓存中唯一标识它。您可以通过运行EVAL并随后调用来验证此行为INFO。

SCRIPT FLUSH

从脚本缓存中移除所有脚本。

SCRIPT LOAD script

将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/540189.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

矢量图形设计工具Affinity Designer 2.04版本在win10系统上的下载与安装配置教程

目录 前言一、Affinity Designer安装二、使用配置总结 前言 Affinity Designer 是一款由 Serif 公司开发的矢量图形设计工具&#xff0c;可用于创建各种类型的设计项目&#xff0c;例如图标、UI 设计、品牌标识、插图和其他类型的矢量图形。 Affinity Designer 工具的详细介绍…

JS解密入门案例:python有道JS解密,做一个简单的翻译程序

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 目录标题 前言本次使用知识点&#xff1a;开发环境:模块使用:思路流程:代码展示尾语 &#x1f49d; 本次使用知识点&#xff1a; 系统分析网页结构 动态数据抓包演示 json数据解析 JS解密 开发环境: Python 3.8 Pycha…

Java形参实参的使用

Java形参实参的使用 形参实参的介绍简单例子稍复杂例子String类 compareTo方法 形参实参的介绍 在JAVA中&#xff0c;形参和实参是非常常见的概念。形参是指在方法定义时声明的参数&#xff0c;用于描述方法需要接收的输入数据类型和变量名&#xff1b;而实参是指在方法调用时…

如何安装EasyRecovery14中文版数据恢复软件

好消息&#xff01;听说数据恢复软件EasyRecovery有了新版本&#xff0c;想必大家在听到这个消息的时候都非常激动&#xff0c;都想看看这个新版本的神秘面纱吧。别着急&#xff0c;下面小编就来教大家使用EasyRecovery14快速恢复数据。 首先我们需要在电脑上下载并安装Ontrac…

​数据库原理及应用上机(实验二 SQL数据定义功能实验)

✨作者&#xff1a;命运之光 ✨专栏&#xff1a;数据库原理及应用上机实验 目录 ✨一、实验目的和要求 ✨二、实验内容与步骤 ✨三、附加练习 ✨四、实验总结 &#x1f353;&#x1f353;前言&#xff1a; 数据库原理及应用上机实验报告的一个简单整理后期还会不断完善&am…

Docker创建Springboot项目镜像文件

Docker创建Springboot项目镜像文件 本文章展示的是以Windows10系统为例进行操作 一.首先在Windows系统安装WSL(Windows系统的Linux子系统) //该命令能够直接在Windows系统安装wsl wsl --install //如果已经安装则可以进行update wsl --update二.安装Docker Desktop在本机电…

C调用Java代码 图文详解

环境搭建 1. android studio2021.2.1 2. JDK版本1.8 一、创建一个android项目 File ——> New ——> New Project ——> Empty Activity 创建后如下图所示 二、C调用java代码过程 2.1 写java类代码 创建一个java的JNI类&#xff0c;写触发C代码&#xff0c;让C…

有意思的各类算法,思维题目分享

1.统计子矩阵 思路&#xff1a;二维前缀和超时&#xff0c;下面是前缀和加双指针&#xff0c;对列前缀和&#xff0c;两个玄幻控制行号&#xff0c;双指针控制列的移动 考查&#xff1a;前缀和双指针 import os import sys# 请在此输入您的代码 # 矩阵大小 N M n,m,kmap(int,…

某大学信息安全竞赛——shellcode1 绕过strlen检查,绕过沙箱检查,执行orw shellcode拿到flag

题目自取&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1HrMqh-lX-mkfueVeLzoEJg 提取码&#xff1a;oyel 介绍下这可恶的沙箱机制 这是一道非常让人蛋疼的题目&#xff0c;之前我只听说过沙箱&#xff0c;但是并没有自己实际接触过沙箱这个保护机制&#xff0c;大…

PX4从放弃到精通(二十八):垂起过渡控制

文章目录 前言一、主程序二、update_transition_state&#xff08;&#xff09;三、update_transition_state&#xff08;&#xff09; 前言 固件版本&#xff1a;1.14.0 可加名片交流学习 一、主程序 代码位置&#xff1a; 构造函数&#xff0c;用初始化列表进行初始化工作…

图可视分析

G6简介 AntVG6是一个基于WebGL的图形可视化引擎&#xff0c;它提供了一种简单、高效、灵活的方式来创建各种类型的图形&#xff0c;包括流程图、关系图、树形图、桑基图、饼图等等。它的主要思想是将图形分解为节点和边&#xff0c;并使用数据来描述它们之间的关系。 它的特性包…

BMPFont使用教程--免费的位图字体制作工具字体制作(2)

1、下载windows免费的位图字体制作工具Bitmap Font Generator 下载地址&#xff1a;BMFont - AngelCode.com 2、打开软件-> Edit -> Open Image Manager 3、点击Image -> Import Image,选择字符对应的图片&#xff0c;id就填写下面的48&#xff0c;代表0&#xff0c;…

Redis 主从复制 哨兵 集群

哨兵&#xff1a;在主从复制的基础上&#xff0c;哨兵实现了自动化的故障恢复。缺陷&#xff1a;写操作无法负载均衡&#xff1b;存储能力收到单机的限制&#xff1b; Cluster集群&#xff1a;通过集群&#xff0c;Redis解决了写操作无法负载均衡&#xff0c;以及存储能力收到…

应用现代化中的弹性伸缩

作者&#xff1a;马伟&#xff0c;青云科技容器顾问&#xff0c;云原生爱好者&#xff0c;目前专注于云原生技术&#xff0c;云原生领域技术栈涉及 Kubernetes、KubeSphere、KubeKey 等。 2019 年&#xff0c;我在给很多企业部署虚拟化&#xff0c;介绍虚拟网络和虚拟存储。 2…

智能图像处理技术:开启未来视觉时代

写在前面技术论坛■ 智能文档图像处理技术■ 大模型时代的文档识别与理解■ 篡改文本图像的生成与检测 圆桌讨论未来愿景 写在前面 文档 是人们在日常生活、工作中产生的信息的重要载体&#xff0c;各领域从业者几乎每天都要与金融票据、商业规划、财务报表、会议记录、合同、…

【JAVA程序设计】(C00138)基于Servlet+jsp的药店管理系统

基于Servletjsp的药店管理系统 项目简介项目获取开发环境项目技术运行截图 项目简介 本项目是简单的药店管理系统&#xff0c;本系统使用servlet和jsp的技术&#xff0c;本系统有一种权限管理员&#xff1a; 其功能有&#xff1a;管理员管理&#xff08;增删改查&#xff09;、…

TypeScript为什么要有对象?怎样创建对象

什么是TypeScript的对象&#xff1f; 生活中&#xff0c;对象是一个具体的事物&#xff0c;比如&#xff1a;你的电脑、你的手机、古力娜扎、周杰伦(周董)等都是对象。 但在程序员的认知中万物皆对象。 这些具体的事物&#xff0c;都有自己的特征和行为&#xff1a; 特征&…

云his门诊业务模块常见问题分析和门诊业务使用流程

一、门诊医生如何查询往期病人 鼠标点击门诊医生站左侧患者列表&#xff0c;在弹出的页面点击已诊分页&#xff0c;在搜索框输入患者姓名&#xff0c;在结果中找到对应患者&#xff0c;点击详情按钮即可查询患者往期就诊信息&#xff0c;点击想要查询的门诊记录前方的方框即可…

[数据结构 -- C语言] 队列(Queue)

目录 1、队列 1.1 队列的概念及结构 2、队列的实现 2.1 接口 3、接口的实现 3.1 初始化队列 3.2 队尾入队列 分析&#xff1a; 3.3 队头出队列 分析&#xff1a; 3.4 获取队列头部元素 3.5 获取队列尾部元素 3.6 获取队列中有效元素个数 3.7 检测队列是否为空 3…

要想抢到演出票,总共分几步?

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 小黑 编辑 / SandLiu 卷圈 监制 / 姝琦 文案 / 小黑 产品统筹 / bobo 录音支持 / 声湃轩天津录音间 报复性听歌正席卷多地&#xff0c;一路狂飙的演唱会市场背后&#xff0c;是一票难求、与黄牛斗智斗勇的粉丝们。 是…