java 中使用 lua 脚本
文章目录不同Lua返回值对应泛型对照表seckill.luaservice实现类代码逐段拆解参数签名返回值 Long result 你的脚本集群坑点重点改写成支持集群的正确版本把key通过Java传入KEYS数组不同Lua返回值对应泛型对照表Lua返回示例Java泛型选什么return 0/1/2数字Longreturn ok字符串Stringreturn {1,2,3}数组ListObjectreturn nilObjectseckill.lua-- 0 成功-- 1 库存不足-- 2 用户重复下单localvouvherIdARGV[1]localuserIdARGV[2]localstockKeyhmdp:seckill:stock:..vouvherIdlocalorderKeyhmdp:seckill:order:..userId-- 判断库存iftonumber(redis.call(get,stockKey))0thenreturn1end-- 判断用户是否已经下单ifredis.call(sismember,orderKey,userId)1thenreturn2end-- 扣库存redis.call(incrby,stockKey,-1)redis.call(sadd,orderKey,userId)return0service实现类Redis 协议里lua脚本返回的整数是64 位有符号整数对应 Java 的long即使数值很小 0、1、2底层依然是 64bit所以 Spring Data Redis 脚本 API 统一使用 Long 接收数字结果。ServicepublicclassVoucherOrderServiceImplextendsServiceImplVoucherOrderMapper,VoucherOrderimplementsIVoucherOrderService{privatestaticfinalDefaultRedisScriptLongSECKILL_SCRIPT;static{SECKILL_SCRIPTnewDefaultRedisScript();SECKILL_SCRIPT.setLocation(newClassPathResource(seckillJvm.lua));SECKILL_SCRIPT.setResultType(Long.class);}OverridepublicResultseckillVoucherAsync(LongvoucherId){LonguserIdUserHolder.getUser().getId();执行 lua 脚本LongresultstringRedisTemplate.execute(SECKILL_SCRIPT,Collections.emptyList(),voucherId.toString(),userId.toString());intrresult.intValue();if(r!0){// 1 库存不足2 用户重复下单returnResult.fail(r1?库存不足:不能重复下单);}}}代码逐段拆解LongresultstringRedisTemplate.execute(SECKILL_SCRIPT,Collections.emptyList(),voucherId.toString(),userId.toString());参数签名TTexecute(RedisScriptTscript,ListStringkeys,Object...args)第一个参数SECKILL_SCRIPT就是我们定义的DefaultRedisScriptLong里面加载了你写的lua脚本文件指定返回类型是Long。第二个参数Collections.emptyList()→ KEYS[]数组即Redis的key名就是你要操作的 Redis 的键Redis 官方要求所有要读写的 Redis key必须通过 KEYS 数组传入不要在 Lua 脚本内部拼接 key 字符串。因为Redis集群模式下Redis 会根据 KEY 做 hash 槽路由如果你脚本里硬编码拼接 key集群环境会报错 CROSSSLOT Keys in request dont hash to the same slot。 对应lua里KEYS[1]、KEYS[2]你的 lua 脚本完全没有使用 KEYS 数组key都是在lua内部字符串拼接localstockKeyhmdp:seckill:stock:..vouvherIdlocalorderKeyhmdp:seckill:order:..userId所以这里 keys 传空集合emptyList()。⚠️ Redis官方最佳实践尽量把key放到KEYS[]参数传入不要lua内部拼接字符串key是为了兼容Redis集群槽位。集群模式下lua脚本操作的key必须全部来自KEYS数组自己拼接会报错CROSSSLOT Keys in request dont hash to the same slot。后面可变参数voucherId.toString(), userId.toString()→ ARGV[]对应lua脚本localvouvherIdARGV[1]localuserIdARGV[2]voucherId.toString()→ARGV[1]userId.toString()→ARGV[2]ARGV 放普通参数 (不是 redis key)没有集群槽位限制可以随便传。返回值 Long resultlua脚本return 0 / 1 / 2底层协议返回64位整数所以Java接收为Long。使用的时候 转换为 intif(result0){// 成功}elseif(result1){// 库存不足}elseif(result2){// 重复下单}注意result 不会是 null脚本一定有 return。 你的脚本集群坑点重点现在写法key在lua内部拼接localstockKeyhmdp:seckill:stock:..vouvherIdlocalorderKeyhmdp:seckill:order:..userId单机Redis正常跑没问题Redis集群环境直接报错跨槽改写成支持集群的正确版本把key通过Java传入KEYS数组Java调用StringstockKeyhmdp:seckill:stock:voucherId;StringorderKeyhmdp:seckill:order:userId;LongresultstringRedisTemplate.execute(SECKILL_SCRIPT,List.of(stockKey,orderKey),// KEYS[1] stockKey , KEYS[2] orderKeyvoucherId.toString(),userId.toString());lua脚本修改-- KEYS[1] stockKey hmdp:seckill:stock:xxx-- KEYS[2] orderKey hmdp:seckill:order:xxx-- ARGV[1] voucherId-- ARGV[2] userIdlocalstockKeyKEYS[1]localorderKeyKEYS[2]iftonumber(redis.call(get,stockKey))0thenreturn1endifredis.call(sismember,orderKey,ARGV[2])1thenreturn2endredis.call(incrby,stockKey,-1)redis.call(sadd,orderKey,ARGV[2])return0集群要求脚本操作的所有 redis key必须全部来自KEYS[]参数不能在lua字符串拼接生成key。

相关新闻

数据库系统原理课后题实战:关系代数、范式分解与索引优化

数据库系统原理课后题实战:关系代数、范式分解与索引优化

简介:《数据库系统原理与设计》第四版课后答案文档,面向正在系统学习数据库原理课程的高校学生与自学者,尤其适合需要逐题核对概念理解、梳理知识框架的备考人群。文档以 doc 格式收录了教材课后习题的详细解答,重点围绕数据、数据…

2026/10/9 13:59:54 阅读更多 →
Dynamo节点包离线打包与还原:packages.zip制作与部署

Dynamo节点包离线打包与还原:packages.zip制作与部署

简介:面向 Revit/Dynamo 用户的离线节点包合集,适合因网络不稳或官方包管理器访问受限,难以在线安装扩展的 BIM 设计师、参数化建模爱好者与二次开发初学者。资源共 2000 个文件,压缩包约 63.86MB,以 .dyf/.dyn 节点定…

2026/10/9 13:59:54 阅读更多 →
SQL Server 2005 安装与 SP3 补丁实战:老系统维护避坑指南

SQL Server 2005 安装与 SP3 补丁实战:老系统维护避坑指南

简介:这份资源是面向数据库初学者与运维人员的 SQL Server 2005 安装图解教程,重点解决版本选择、环境准备与补丁升级等入门难题。内容围绕 Enterprise、Standard、Workgroup、Developer、Express 五个版本的适用场景展开,并说明软件平台对 W…

2026/10/9 13:59:54 阅读更多 →

最新新闻

PIC18F87J10与PCA9422协同实现电池供电系统的动态电源管理

PIC18F87J10与PCA9422协同实现电池供电系统的动态电源管理

做电池供电的便携设备时,电源管理往往比业务逻辑更让人头疼。之前我把 PCA9422 和 PIC18F87J10 搭在一起做了一套完整的电源管理方案,从硬件设计、I2C 配置、动态调压到低功耗切换都实际跑了一遍。这篇文章就是这次实践的整体记录,核心思路是…

2026/10/9 14:30:56 阅读更多 →
机械设计必看:CATIA、SolidWorks、UG、Pro/E四款软件选型解析

机械设计必看:CATIA、SolidWorks、UG、Pro/E四款软件选型解析

这标题一看就是刚入行的朋友最喜欢问的问题。我当年也是这么过来的,在宿舍里把四款软件装了个遍,挨个折腾,最后才明白一个道理: 没有“最顺手”的软件,只有“最适合你当前做的事情”的软件。 拿着CATIA去画一个简单的…

2026/10/9 14:30:56 阅读更多 →
PCA9422 + TM4C1294:电池供电设备PMIC与MCU协同电源管理设计

PCA9422 + TM4C1294:电池供电设备PMIC与MCU协同电源管理设计

直接上结论:这套“PCA9422 TM4C1294NCZAD”组合,适合做电池供电的工业采集终端、便携式仪表和物联网边缘节点,核心思路是把“实时功率级控制”交给集成化 PMIC,把“充电策略、状态监控、低功耗调度”交给 MCU。我之前在接触这类嵌…

2026/10/9 14:30:56 阅读更多 →
基于PCA9422与TM4C123的低功耗电源管理设计实战

基于PCA9422与TM4C123的低功耗电源管理设计实战

做电源管理的人大多都有过这种经历:板子画完、固件跑通,结果一测功耗,待机电流比预期高一个数量级,电池没撑过两天就报警。真正把功耗压下去,靠的不只是挑几颗低静态电流的LDO,而是整套供电架构和控制策略。…

2026/10/9 14:30:56 阅读更多 →
ArcGIS基础地理空间数据库系统设计:从建库到出图全流程

ArcGIS基础地理空间数据库系统设计:从建库到出图全流程

简介:这份PDF文档面向地理信息系统、测绘与空间数据库方向的学习者与工程技术人员,围绕基于ArcGIS的基础地理空间数据库系统设计展开,帮助读者理解空间数据与属性数据统一管理的整体思路。文档重点讲解空间数据库建库组织、点面体三类数据分类…

2026/10/9 14:30:56 阅读更多 →
CAP理论与数据库分片架构:一致性、可用性与分库分表实战解析

CAP理论与数据库分片架构:一致性、可用性与分库分表实战解析

做分布式系统做了这么久,我发现一个特别有意思的现象:很多人都把CAP背得滚瓜烂熟,一问你“CAP是什么”,张口就来“一致性、可用性、分区容错性,三者不可兼得”。可真到设计一个数据库分片架构的时候,该选什…

2026/10/9 14:29:54 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →