当前位置: 首页 > news >正文

Redis系列之使用Lua脚本

什么是lua脚本?

lua语言是一个轻量级的脚本语言,可以嵌入其他语言中使用,调用宿主语言的功能。lua语法简单,小巧,源码一共才200多K,本身不会有太强的功能,很多的语言也支持lua语言,比如redis、Nginx

redis语言中完美嵌入了lua脚本功能,redis可以调用lua脚本中的api,lua脚本也可以调用redis中的命令

redis调用lua脚本

在redis中调用lua脚本,需要使用eval指令

127.0.0.1:6379>eval "return 'hello'" 0
"hello"

调用lua脚本,动态传入参数,其中表达式script后面第一个参数nkey表示key的对应位置,后面的表示key和对应的参数argv

# script脚本后面,第一个参数1表示key为其后的第一个参数,也就是1,如何key后面的参数都是ARGV
127.0.0.1:6379>eval "if KEYS[1]=='1' then return ARGV[1] end return ARGV[2]" 1 1 'hello' 'hi'
"hello"
127.0.0.1:6379>eval "if KEYS[1]=='1' then return ARGV[1] end return ARGV[2]" 1 1 'hello' 'hi'
"hi"

lua脚本调用redis命令

使用lua调用redis的命令,需要使用redis.call调用

# key为0表示能获取到锁
127.0.0.1:6379>eval "local key = redis.call('exists',KEYS[1]) if key==0 then return redis.call('set',KEYS[1],ARGV[1]) end return 1" 1 orderId01 1

写个lua脚本,来实现一个简单的分布锁锁

private static final String LOCK_LUA_SCRIPT = "local lockParam = redis.call('exists', KEYS[1])\n" +"if lockParam == 0 then\n" +"redis.call('set', KEYS[1], ARGV[1])\n" +"redis.call('expire', KEYS[1], ARGV[2])\n" +"end\n" +"return lockParam\n";

简单实现抢单的业务

  @Autowiredprivate RedisTemplate redisTemplate;@Testpublic void testLua() {Long orderId = IdUtil.getSnowflake().nextId();String lockKey = "order:"+orderId;String requestId = IdUtil.randomUUID();try {Long lock = (Long) redisTemplate.execute(RedisScript.of(LOCK_LUA_SCRIPT, Long.class), Arrays.asList(lockKey), requestId, 30);// 抢得到锁if (lock == 0) {// 模拟业务执行10sTimeUnit.MILLISECONDS.sleep(10*1000);}log.info("lock:[{}]", lock);} catch (Exception e) {testRelease(lockKey, requestId);} finally {testRelease(lockKey, requestId);}}

锁释放的,也通过lua脚本实现,主要是保证原子性

 private String UNLOCK_LUA_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";@Test
public void testRelease(String lockKey, String lockValue) {redisTemplate.execute(RedisScript.of(UNLOCK_LUA_SCRIPT, Long.class), Arrays.asList(lockKey), lockValue);
}

Lua脚本使用场景

  • 保证原子性地执行多个命令
  • 需要返回中间值组合编排后面的命令
http://www.lryc.cn/news/279900.html

相关文章:

  • Wargames与bash知识16
  • 关于运维·关于数据库面试题
  • MySQL题目示例
  • HTML基本语法
  • 二分图最大匹配——匈牙利算法详解
  • 【AI视野·今日Robot 机器人论文速览 第七十一期】Fri, 5 Jan 2024
  • xtu oj 1334 Least Common Multiple
  • 【论文笔记】End-to-End Diffusion Latent Optimization Improves Classifier Guidance
  • 【HarmonyOS4.0】第四篇-ArkUI基础实战
  • 每日一题——LeetCode1128.等价多米诺骨牌对的数量
  • 关联规则分析(Apriori算法2
  • 数据仓库(2)-认识数仓
  • C#编程-实现委托
  • Ubuntu18.04 Qt 实现MQTT
  • 【软件测试】学习笔记-不同视角的软件性能与性能指标
  • Spring MVC组件
  • vue文件在<template>中使用多个<el-main>报错(已解决)
  • 【PlantUML】- 时序图
  • openai自定义API操作 API (openai.custom):OpenAI API 实现电商平台的智能库存管理
  • 宠物服务新篇章:预约小程序带来的变革
  • 谷歌最新医学领域LLM大模型:AMIE
  • 路由器02_静态路由DHCP
  • Mysql 递归查询所有子节点,hutool树形结构封装
  • 【代码随想录04】24. 两两交换链表中的节点 19. 删除链表的倒数第 N 个结点 面试题 02.07. 链表相交 142. 环形链表 II
  • Pandas实战100例 | 案例 25: 计算相关系数
  • vue文本识别“\n“换行问题的解决方式
  • 【QT-UI】
  • MyBatisPlus逆向工程
  • 创建ESP32开源WiFi MAC(介质访问控制)层
  • LeetCode 2723. 两个 Promise 对象相加