Lua脚本的使用
一、使用lua脚本扣减单个商品的库存
@SpringBootTest
class LuaTests {@AutowiredStringRedisTemplate stringRedisTemplate;@Testvoid test3() {for (int i = 1; i <= 5; i++) {stringRedisTemplate.opsForValue().set("product."+i,String.valueOf(i));}}@Testvoid test2() {StringBuilder sb = new StringBuilder();sb.append(" local key = KEYS[1] "); // 你要扣减的key :product.1sb.append(" local qty = ARGV[1] "); // 你要扣减的数量,需求量sb.append(" local redis_qty = redis.call('get',key) "); //获取redis库存实际数量sb.append(" if tonumber(redis_qty) >= tonumber(qty) then ");//需求量与库存量对比sb.append(" redis.call('decrby',key,qty) "); //满足sb.append(" return -1 "); //满足sb.append(" else ");sb.append(" return tonumber(redis_qty) "); //不满足,就给剩余库存量 ,0 1 2 。。。。sb.append(" end ");RedisScript<Long> luaScript = RedisScript.of(sb.toString(), Long.class);ExecutorService executorService = Executors.newFixedThreadPool(5);for (int i = 1; i <= 5; i++) {executorService.execute(()->{int qty = RandomUtil.randomInt(1,6);Long count = stringRedisTemplate.execute(luaScript, CollUtil.newArrayList("product.5"),String.valueOf(qty));if (count == -1L) {System.out.println(Thread.currentThread().getId() + " 扣减成功,扣减了-> "+ qty);} else {System.out.println(Thread.currentThread().getId() + "扣减失败,需求量是:"+qty+",剩余库存量:"+count);}});}// 线程睡眠3秒 ThreadUtil.safeSleep(3000);}
}
二、使用lua脚本扣减多个商品的库存
@Testvoid test4() {StringBuilder sb = new StringBuilder();sb.append(" local table = {} "); // 你要扣减的key :product.1sb.append(" local values = redis.call('mget', unpack(KEYS) )"); // [product.1,product.2] => product.1 product.2sb.append(" for i = 1, #KEYS do ");sb.append(" if tonumber(ARGV[i]) > tonumber(values[i]) then ");// ..的意思就是组合,也就是字符串相加sb.append(" table[#table + 1] = KEYS[i] .. '=' .. values[i] "); //product.1=23sb.append(" end ");sb.append(" end ");sb.append(" if #table > 0 then ");sb.append(" return table ");sb.append(" end ");sb.append(" for i = 1 , #KEYS do ");sb.append(" redis.call('decrby',KEYS[i],ARGV[i]) ");sb.append(" end ");sb.append(" return {} ");RedisScript<List> luaScript = RedisScript.of(sb.toString(), List.class);List<StockProduct> stockProducts = new ArrayList<>();stockProducts.add(new StockProduct(5,1));stockProducts.add(new StockProduct(4,2));List<String> keys = stockProducts.stream().map(it -> "product." + it.getId()).collect(Collectors.toList());Object[] qtys = stockProducts.stream().map(it -> it.getQty() + "").toArray();List<String> list = stringRedisTemplate.execute(luaScript,keys,qtys);if(list.isEmpty()){System.out.println("库存冻结成功");} else {for (String key_qty : list) {String[] split = key_qty.split("=");System.out.println(split[0] + "库存不足,剩余库存量:" + split[1]);}}ThreadUtil.safeSleep(3000);}
三、通过分布式锁,扣减商品的库存
package com.by;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import com.by.moder.Student;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@SpringBootTest
class SetNXTests {@AutowiredStringRedisTemplate stringRedisTemplate;// @Autowired@Resource(name = "redisTemplate")ValueOperations<String,String> valueOperations;@Testvoid Test() {//线程池ExecutorService executorService = Executors.newFixedThreadPool(5);for (int i = 1; i <=5; i++) {executorService.execute(()->{//某一个工人String ioId = "IO"+ RandomUtil.randomInt(1,1000);while (true){// 判断是否存在Boolean b = valueOperations.setIfAbsent("lock.product.1",ioId+":"+ DateUtil.now());if(b){System.out.println(Thread.currentThread().getId()+"获取到了分布式锁");//执行业务ThreadUtil.safeSleep(3000);// 执行业务成功后stringRedisTemplate.delete("lock.product.1");System.out.println(Thread.currentThread().getId()+"释放了分布式锁");break;}else {//Thread.currentThread().getId() :当前线程的idSystem.out.println(Thread.currentThread().getId()+"没有获取到分布式锁");ThreadUtil.safeSleep(1000);}}});}//睡眠ThreadUtil.safeSleep(100000);}
}
相关文章:
Lua脚本的使用
一、使用lua脚本扣减单个商品的库存 SpringBootTest class LuaTests {AutowiredStringRedisTemplate stringRedisTemplate;Testvoid test3() {for (int i 1; i < 5; i) {stringRedisTemplate.opsForValue().set("product."i,String.valueOf(i));}}Testvoid test…...
hcia datacom课程学习(5):MAC地址与arp协议
1.MAC地址 1.1 含义与作用 (1)含义: mac地址也称物理地址,是网卡设备在数据链路层的地址,全世界每一块网卡的mac地址都是唯一的,出厂时烧录在网卡上不可更改 (2)作用:…...
unbuntu mysql8.0新建用户及开启远程连接
MySQL更新到8.0以上版本后,在创建连接远程的用户的时候和之前5.x的版本有了很大的不同,不能使用原来同时创建用户和授权的命令。 以下是记录的MySQL8.0创建用户并授权的命令: 查看用户表: user mysql; select host,user,authen…...
Intel FPGA (1):线性序列机
Intel FPGA (1):线性序列机 前提摘要 个人说明: 限于时间紧迫以及作者水平有限,本文错误、疏漏之处恐不在少数,恳请读者批评指正。意见请留言或者发送邮件至:“Email:noahpanzzzgmail.com”。本博客的工程文件均存放在…...
翻译: 硅谷软件工程师面试:准备所需的一切
没有人有时间去做成百上千道LeetCode题目,好消息是你实际上并不需要做那么多题目就能够在FAANG公司找到工作! 我曾经在Grab工作,这是东南亚的一家共享出行公司,但我对工作感到沮丧,想要进入FAANG公司,但我…...
视频推拉流EasyDSS点播平台云端录像播放异常的问题排查与解决
视频推拉流EasyDSS视频直播点播平台可提供一站式的视频转码、点播、直播、视频推拉流、播放H.265视频等服务,搭配RTMP高清摄像头使用,可将无人机设备的实时流推送到平台上,实现无人机视频推流直播、巡检等应用。 有用户反馈,项目现…...
kubuntu23.10安装sdl2及附加库和 sfml2.5.1
2024年3月28号,四,晚上kubuntu23.10下安装了sdl2的如下,没有安装gfx。 sudo apt install libsdl2-dev sudo apt install libsdl2-image-dev sudo apt install libsdl2-ttf-dev sudo apt install libsdl2-mixer-dev sudo apt install libsdl2…...
Centos JDK1.8 下载安装
https://www.oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html 一 RPM包安装 rpm -ivh jdk-8u391-linux-x64.rpm /etc/profile export JAVA_HOME/usr/java/jdk1.8.0-x64 export PATH$JAVA_HOME/bin:$PATHsource /etc/profile二 tar.gz 包手动…...
iOS开发进阶(十四):xcodebuild 命令应用详解
文章目录 一、前言二、xcodebuild 命令汇总三、xcodebuild 可选命令四、exportOptionsPlist文件内容配置说明五、项目实操六、拓展阅读 一、前言 关于iOS组包,详参博文《ReactNative进阶(三十四):Jenkins 流水线 组包 iOS 应用包…...
uniapp 开发之原生Android插件
开发须知 在您阅读此文档时,我们假定您已经具备了相应Android应用开发经验,使用Android Studio开发过Android原生。也应该对HTML,JavaScript,CSS等有一定的了解, 并且熟悉在JavaScript和JAVA环境下的JSON格式数据操作等。 为了插件开发者更方便快捷的开…...
构建第一个JS应用(FA模型)
创建JS工程 若首次打开DevEco Studio,请点击Create Project创建工程。如果已经打开了一个工程,请在菜单栏选择File > New > Create Project来创建一个新工程。选择Application应用开发(本文以应用开发为例,Atomic Service对…...
物联网学习2、MQTT 发布/订阅模式介绍
MQTT 发布/订阅模式 发布订阅模式(Publish-Subscribe Pattern)是一种消息传递模式,它将发送消息的客户端(发布者)与接收消息的客户端(订阅者)解耦,使得两者不需要建立直接的联系也不…...
docker--部署 (超详版) (五)
环境准备:docker,mysql,redis,镜像,nginx 把虚拟机打开,连接xshell,参考博客: https://blog.csdn.net/m0_74229802/article/details/136965820?spm1001.2014.3001.5501 一&#x…...
谷粒商城——通过接口幂等性防止重复提交订单
如果用户向后端服务提交多次相同订单的提交服务,那么后端应该只生成一条订单记录。 有一些操作天然是幂等的,如查询操作和删除操作等。 幂等性实现 1.token机制(仅这个方法适用于订单的重复提交) 后端先生成1个令牌将其记录在R…...
谈谈MVCC机制
在MySQL中,MVCC(多版本并发控制)是InnoDB存储引擎使用的并发控制机制。它提供对数据的并发访问,并确保多用户环境中数据的一致性和隔离性。 InnoDB通过“Undo log”存储每条记录的多个版本,提供历史记录供读取&#x…...
Linux之用户账号、用户组和与账号有关的系统文件
目录 一、基本介绍 1.用户和用户组 2.UID和GID 二、 账户管理 1.查看用户的UID和GID 2.添加账户 3.删除账号 4.修改账号 5.账户口令 三、分组管理 1.新增用户组 2.删除用户组 3.修改用户组 4.用户组切换 四、与账号有关的系统文件 1./etc/passwd 2./etc/shado…...
mac 安装 pip,如果你的电脑已经有 python3
文章目录 如果没装 如果你的电脑已经有 python3. 安装 pip 执行以下命令, 输入 python3 -m ensurepip --upgrade ,按下Enter就大功告成了! 安装后查看版本: pip3 -V 如果没装 先安装 python,建议使用 homebrew。 …...
java 枚举
枚举的格式 枚举是一种特殊的类 枚举类的最开始必须罗列所有类型 枚举类提供了一些父类的方法 values() :获取所有的的枚举对象,是一个数组 public enum A {A1, A2, A3;String name;A() {this.name "default";}String getName() {return name;}void setName(Strin…...
Java学习之类和对象、内存底层
目录 表格结构和类结构 表格的动作和类的方法 与面向过程的区别 具体实现 对象和类的详解 类的定义 属性(field 成员变量) 方法 示例--编写简单的学生类 简单内存分析(理解面向对象) 构造方法(构造器 constructor) 声明格式: 四…...
递归遍历目录结构和树状展现
在D盘下创建文件夹“电影”,在文件夹“电影”下创建“华语”、“好莱坞”,在文件夹“华语”下创建文件“人民的名义.mp4”、“天安门传奇.mp4”、“程序员统治世界.mp4”,在文件夹“好莱坞”下创建文件“国王的演讲.mp4”、“速度与激情8.mp4…...
【C++的奇迹之旅(二)】C++关键字命名空间使用的三种方式C++输入输出命名空间std的使用惯例
文章目录 📝前言🌠 C关键字(C98)🌉 命名空间🌠命名空间定义🌉命名空间使用 🌠命名空间的使用有三种方式:🌉加命名空间名称及作用域限定符🌠使用using将命名空间中某个成员…...
如何通过针对iOS的动态分析技术绕过反调试机制
在这篇文章中,我们将跟大家介绍和分析一种针对iOS的新型安全研究技术,该技术能够让iOS应用程序的调试过程更加轻松,并解决那些可能会延缓我们步伐的阻碍。 如果你要对一个采用了反调试技术的iOS应用程序或二进制文件进行调试的话,…...
33.Python从入门到精通—Python3 正则表达式 re.match函数 re.search方法 re.match与re.search的区别
33.从入门到精通:Python3 正则表达式 re.match函数 re.search方法 re.match与re.search的区别 Python3 正则表达式re.match函数re.search方法re.match与re.search的区别 Python3 正则表达式 在 Python3 中,可以使用 re 模块来进行正则表达式的匹配和处理…...
便携式气象站是什么
TH-BQX5便携式气象站是一种用于应对突发天气灾害和紧急情况的便携式气象监测设备。它通常包括气温、湿度、气压、风速、风向和降水量等关键气象要素的测量功能,能够快速准确地记录这些气象参数。此外,一些高级的便携式气象站还具备预警功能,当…...
AIGC重塑金融:AI大模型驱动的金融变革与实践
随着人工智能技术的飞速发展,AI大模型在金融领域的应用日益广泛,正在深刻改变着金融行业的面貌。本文将探讨AIGC(人工智能与金融结合)如何重塑金融,以及AI大模型驱动的金融变革与实践。 AIGC重塑金融的背景与意义 随着…...
TP4054替代DP4054锂电池供电电路保护方案
锂离子电池以其优良的特性,被广泛应用于:手机、摄录像机、笔记本电脑、无绳电话、电动工具、遥控或电动玩具、照相机等便携式电子设备中。 01 电池特点 1、具有更高的重量能量比、体积能量比; 2、电压高,单节锂电池电压为3.6V,等…...
前端JS商品规格组合
给定一个数组 let data [{name: "颜色",specs: ["白色", "黑色"],},{name: "尺寸",specs: ["14寸","15寸", "16寸"],},{name: "处理器",specs: ["i5", "i7", "i9&…...
⾃定义类型:联合和枚举
乐观学习,乐观生活,才能不断前进啊!!! 我的主页:optimistic_chen 我的专栏:c语言 点击主页:optimistic_chen和专栏:c语言, 创作不易,大佬们点赞鼓…...
Spring IOC控制反转、DI注入以及配置
1.使用xml的方式进行配置IOC容器,首先引入依赖 在Resource资源下配置,applicationContext.xml ,刷新mevan后可以直接选择配置spring.xml文件 <!-- spring核心用来管理bean --><dependency><groupId>org.springframework</g…...
RabbitMQ的部分模式
1发布订阅模式 发送者 package org.example; import com.alibaba.fastjson.JSON; import com.rabbitmq.client.BuiltinExchangeType; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import ja…...
企业网站建设市场报价/怎么进行seo
很好(供应商msgSupplier):使用此方法来记录FINE消息,仅当记录级别足以实际记录该消息时才构造。这意味着,如果为FINE消息级别启用了记录器,则通过调用提供的供应商功能来构造消息,并将其转发给所有已注册的输出Handler…...
淄博网站备案/网络推广的优化服务
文章目录Formal软件成本评估成本评估过程中的挑战(challenges)可能的策略(possible solutions)可用的技术(Techniques)Expert judgementAnalogyParkinsons LawPricing to winAlgorithmic cost modelling (算…...
网站建设策划书格式及范文/网络推广外包公司
如何在控制台获取到某个元素的Scope呢?假设,页面元素为:<label>Name:</label><input type"text" ng-model"yourName" placeholder"Enter a name here"><h1>{{yourName}}</h1>→…...
wordpress目录分类与菜单/销售网站怎么做
前言计算机中储存的信息都是用二进制数表示的;而我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果。通俗的说,按照何种规则将字符存储在计算机中,如a用什么表示,称为"编码";反之,将存…...
wordpress注册页面修改/百度搜索引擎怎么弄
目录题目描述动归五部曲代码如下题目描述 动归五部曲 代码如下 class Solution {public int numTrees(int n) {int[] dp new int[n1];dp[0] 1;for(int i 1; i<n ; i){for(int j 1; j <i; j){dp[i] dp[j-1] * dp[i-j]; // 注意,这里是 不是 ,…...
wordpress 文章编辑 插件/互联网推广广告
Akka 和 Storm 的设计差异 Akka 和 Storm 都是实现低延时, 高吞吐量计算的重要工具. 不过它们并非完全的竞品,如果说 Akka 是 linux 内核的话, storm 更像是类似 Ubuntu 的发行版.然而 Storm并非 Akka 的发行版, 或许说 Akka 比作 BSD, Storm 比作 Ubuntu 更合适. 实现的功能差…...