Lua脚本 快速把握

[复制链接]
发表于 2026-2-9 01:33:59 | 显示全部楼层 |阅读模式
1.Lua脚本概述

Lua是一种轻量级的编程语言,由巴西里约热内卢天主教大学开辟。筹划初志是为了嵌入应用步调中,提供机动的设置和脚本本事。Lua具有简便的语法和强盛的扩展性,使得它在多个范畴得到了广泛应用。
Lua的特点包罗动态范例、主动内存管理、协程、模块和包支持。它使用表(Table)这一数据布局来实现关联数组、聚集等多种功能。Lua的实验速率快,且库体积小。
教程链接:Lua 教程 | 菜鸟教程 (runoob.com)
2.快速入门实操:

(1)创建lua脚本

比方在resource下创建名为unlock.lua的脚本:
  1. if(redis.call('get',KEYS[1]) == ARGV[1]) then
  2.     return redis.call('del',KEYS[1])
  3. end
  4. return 0
复制代码
分析:


  • if 是Lua的条件判定关键字。
  • redis.call 是Lua脚本中调用Redis下令的方法。在这里,它调用了Redis的 GET 下令。
  • KEYS[1] 是一个特别变量,代表通报给Lua脚本的键名列表中的第一个键。
  • ARGV[1] 是另一个特别变量,代表通报给Lua脚本的参数列表中的第一个参数。
  • end 标记着if语句块的竣事。
  • 如果if条件不创建(即键值不匹配),则实验这个 return 语句。
  • 返回值 0 表现没有举行任何利用。
(2)编写代码

  1.     private static final String KEY_PREFIX = "lock:";
  2.     private static final String ID_PREFIX = UUID.randomUUID().toString();
  3.     // 定义一个静态常量 UNLOCK_SCRIPT,类型为 DefaultRedisScript,预期返回值类型为 Long
  4.     private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
  5.     // 静态初始化块,用于初始化静态常量 UNLOCK_SCRIPT
  6.     static{
  7.         UNLOCK_SCRIPT = new DefaultRedisScript<>();
  8.         // 设置 Lua 脚本的路径,这里脚本是从类路径下的资源文件 "unlock.lua" 中加载
  9.         UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
  10.         // 指定脚本执行后的返回值类型为 Long.class
  11.         UNLOCK_SCRIPT.setResultType(Long.class);
  12.     }
  13.     @Override
  14.     public boolean tryLock(long timeoutSec) {
  15.         String threadId = ID_PREFIX + Thread.currentThread().getId();
  16.         Boolean flag  = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX+name,threadId,timeoutSec, TimeUnit.SECONDS);
  17.         return Boolean.TRUE.equals(flag);
  18.     }
  19.     @Override
  20.     public void unlock(){
  21.         // 使用 StringRedisTemplate 执行 Lua 脚本 UNLOCK_SCRIPT
  22.         stringRedisTemplate.execute(
  23.                 // 传递预定义的 Lua 脚本对象 UNLOCK_SCRIPT
  24.                 UNLOCK_SCRIPT,
  25.                 // 传递一个包含锁键的列表,这里锁键由前缀和锁的名称组成
  26.                 Collections.singletonList(KEY_PREFIX + name),
  27.                 // 传递一个参数,该参数是线程 ID 前缀加上当前线程的 ID
  28.                 ID_PREFIX + Thread.currentThread().getId());
  29.     }
复制代码
3.相识Spring Data Redis提供的execute方法

查察源码可以知道execute方法可知
第一个参数:确定返回的范例值和脚本文件的位置
第二个参数:通报给脚本文件key的值,如果没有想通报的key值可以通报为空的Collections.emptyList()。在脚本文件中通过KEYS[序号]获取,比方KEY[1]表现第一个Key的值
之后的参数:通报给脚本文件arg的值,在脚本文件中通过ARGV[序号]获取,比方AVG[1]表现第一个arg的值

 4.更复杂的lua脚本示例代码

这里只写了lua脚本,还必要在使用Spring Data Redis提供的 execute方法才华运行,
  1. -- 优惠卷ID,通过ARGV参数传递,ARGV[1]是第一个参数
  2. local voucherId  = ARGV[1]
  3. -- 用户ID,通过ARGV参数传递,ARGV[2]是第二个参数
  4. local userId = ARGV[2]
  5. -- 订单ID,通过ARGV参数传递,ARGV[3]是第三个参数
  6. local orderId = ARGV[3]
  7. -- 库存Key,拼接字符串构建库存的Redis键名
  8. local stockKey = 'seckill:stock:' .. voucherId
  9. -- 订单Key,拼接字符串构建订单的Redis键名
  10. local orderKey = 'seckill:order:' .. voucherId
  11. -- 脚本业务逻辑开始
  12. -- 检查库存是否充足,使用get命令获取库存数量,如果库存小于等于0则返回1
  13. if(tonumber(redis.call('get',stockKey)) <=0 ) then
  14.     -- 库存不足,返回1,这里1通常表示库存不足的错误码
  15.     return 1
  16. end
  17. -- 判断用户是否已经下过单,使用sismember命令检查订单集合中是否包含该用户ID
  18. -- 如果用户已存在订单集合中,返回2
  19. if(tonumber(redis.call('sismember',orderKey,userId)) == 1 ) then
  20.     -- 用户已下单,返回2,这里2通常表示用户重复下单的错误码
  21.     return 2
  22. end
  23. -- 如果库存充足且用户未下单,则减少库存数量,使用incrby命令对库存进行减一操作
  24. redis.call('incrby',stockKey,-1)
  25. -- 将用户ID添加到订单集合中,记录用户已下单,使用sadd命令添加集合元素
  26. redis.call('sadd',orderKey,userId)
  27. -- 将订单信息发送到消息队列中,使用xadd命令向stream.orders消息队列添加一条消息
  28. -- '*': 表示自动生成消息ID
  29. -- 'userId',userId: 消息字段名为userId,值为脚本传入的userId
  30. -- 'voucherId',voucherId: 消息字段名为voucherId,值为脚本传入的voucherId
  31. -- 'id',orderId: 消息字段名为id,值为脚本传入的orderId
  32. -- 发送消息到队列中 XADD stream.orders * k1 v1 k2 v2
  33. --(下面的key值请参考实体类所定义的,因为这个lua脚本是创建订单信息,所以oderId对应实体的id)
  34. redis.call('xadd','stream.orders','*','userId',userId,'voucherId',voucherId,'id',orderId)
  35. -- 如果脚本执行至此,表示操作成功,返回0
  36. return 0
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表