- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
Redis官方文档: https://redis.io/docs/manual/programmability/eval-intro/ 。
。
Redis 保证脚本的原子执行。在执行脚本时,所有服务器活动在其整个运行期间都被阻止。这些语义意味着脚本的所有效果要么尚未发生,要么已经发生.
脚本提供了几个在许多情况下都很有价值的属性。这些包括:
Lua 允许您在 Redis 中运行部分应用程序逻辑。这样的脚本可以跨多个键执行条件更新,可能以原子方式组合几种不同的数据类型.
。
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.call() 或从 Lua 脚本调用 Redis 命令 redis.pcall() .
两者几乎一模一样。两者都执行 Redis 命令及其提供的参数(如果这些参数表示格式正确的命令)。但是,这两个函数之间的区别在于处理运行时错误(例如语法错误)的方式。调用函数引发的错误 redis.call() 直接返回给执行它的客户端。相反,调用 redis.pcall() 函数时遇到的错误将返回到脚本的执行上下文,而不是进行可能的处理.
注意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 添加到脚本缓存中,但并不立即执行这个脚本. |
最后此篇关于Redis使用lua脚本实现库存扣减的文章就讲到这里了,如果你想了解更多关于Redis使用lua脚本实现库存扣减的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是 PrestaShop 的新手。我遇到了一个问题,无法在 PrestaShop 从库存中减去商品的代码中找到。 当客户创建订单并选择付款时,商品将从库存中减去,但如果客户不付款并返回,则商品不会退
是否有最好的方法在关系数据库中存储诸如玩家背包之类的数据? 假设我想将玩家背包存储在数据库中。 表“eq”的数据库模型如下所示: 玩家 ID |槽 |商品编号 |金额 现在假设我在数据库中有这一行:
有没有一种方法可以在不使用 [all:vars] 的情况下在组之间继承变量 例子: [GROUP_A] server-A1 [GROUP_A:vars] vpc_cidr="192.10.0.0/21
我的 WooCommerce 插件遇到技术问题,但似乎无法找到答案。我得到了一个可变产品,有两个不同的研讨会时间。举一个简单的例子: 产品:事件当天门票 研讨会 1:红色 |蓝色|绿色 研讨会 2:红
我正在制作一个需要访问用户的 Steam 库存的网站。我找到了一个用于获取 Team Fortress 2 库存、Dota 2、CS:S、CS:GO 和 Portal 2 的 API。但我没有找到任何
我正在建立一个 woocommerce 网上商店。 这是一家手机壳网店,客户想在 woocommerce 后台保留库存,只有一个问题: 它们有不同的型号,例如 iPhone 4 和 iPhone 5。
我在 CodeBlocks (Windows 7) 中使用 GTK,并尝试创建 gtk_button_new_from_stock 所以我使用了以下代码: #include #include in
我有一个名为“条目”的表,我在其中保存每日销售和购买交易/条目。 “条目”表如下所示: ---条目表--- EntryDate EntryType Item Qty Rate
假设我有以下两条记录; tran_id item_id qty_in qty_out price 1 1 15
当我点击元素栏中的元素时,它什么都不做,我可以将它拖到任何我想要的地方。然后我重新打开库存,元素又回来了。我希望单击该项目(在本例中为通知项目)以切换通知 boolean 值并关闭库存。请帮忙。这可能
(我使用的是 Java,因此添加了“Java”标签,以防它影响任何答案,但有些人可能会认为该标签是不必要的。) 考虑以下因素: 我有一个阳台/阳台可以进行图形规划。作为最终计划的一部分,我需要列出 b
我有 2 个表 Tblinkreceiving 和 Tblinkdelivery。我想显示每个 inkcode 的库存余额。我尝试了下面的 sql 连接查询,但当我交叉检查手动计算时,许多 inkco
所以在很大程度上我明白我做错了什么,问题是我不知道如何解决它。 目标:这是一个必须包含可操作的菜单和库存管理功能的商店管理系统。为此,我使用数组来添加商店的商品、它们的描述和它们的数量。所有数组都部分
我发现设置 pg_hba.conf 文件非常困难。这是浪费我时间的常见情况。我需要做什么? 首先,在 Amazon、Digital Ocean 或我自己的硬件上安装新安装的 Linux 发行版的虚拟机
我正在尝试修改旨在与 HTML5 和 Javascript 一起使用的库存列表 Dynagrid 演示,它最初设计用于每次订阅订阅一个项目。 在我的例子中,我已将此演示连接到我的 lightstrea
元素以件和盒子的形式出现。 例如假设, 我购买了 100 片(片剂)medicineX。 我购买了一盒,其中包含50 medicineY。 现在元素仅按件分配。 意味着 MedicineX 将根据他们
我正在尝试使用 Terraform 中的 local_file 函数创建 Ansible 库存文件(我愿意接受以不同方式执行此操作的建议) 模块“vm”配置: resource "azurerm_li
我正在尝试使用 Terraform 中的 local_file 函数创建 Ansible 库存文件(我愿意接受以不同方式执行此操作的建议) 模块“vm”配置: resource "azurerm_li
我想知道是否有更有效/更干净的方法来执行以下操作。假设我有一个包含 2 列的数据框,百分比(基于之前的价格)和操作,玩/买 (1) 或不玩/卖 (-1)。它基本上与股票有关。 为简单起见,请考虑示例
不确定如何表达,但我正在创建一个音乐应用程序,并且我有一个流派选项卡按钮,该按钮将流派列为 UICollectionView 中的单元格。 然后用户选择一个流派,比如“Hip-Hop”,然后会显示相应
我是一名优秀的程序员,十分优秀!