Lua脚本使用手册(Redis篇)

Lua脚本

**简介:**Lua是一种功能强大的,高效,轻量级,可嵌入的脚本语言。它是动态类型语言,通过使用基于寄存器的虚拟机解释字节码运行,并具有增量垃圾收集的自动内存管理,是配置,脚本和快速原型设计的最佳选择

Redis中使用lua脚本的原因
  • 减少网络延迟:Lua脚本将多个Redis命令组合成一个脚本,减少了客户端与服务器之间的网络交互。同时,Redis服务器还提供了EVALSHA命令,可以将脚本的SHA1值缓存在服务器中,下次再执行同样的脚本时,只需传递SHA1值即可,减少了网络传输时间。

  • 原子操作:Lua脚本可以保证多个Redis命令的原子性,避免了并发问题

Redis怎么执行Lua脚本
1、lua函数

Lua脚本使用两个不同的Lua函数来调用任意的Redis命令

redis.call()
redis.pcall()

当redis命令执行结果返回错误时

  • call() 将返回给调用者一个错误,

  • pcall() 将捕获的错误以Lua表的形式返回

127.0.0.1:6379> EVAL "return redis.call('xxxx')" 0
(error) ERR Error running script (call to f_1e6efd00ab50dd564a9f13e5775e27b966c2141e): @user_script:1: @user_script: 1: Unknown Redis command called from Lua script127.0.0.1:6379> EVAL "return redis.pcall('xxxx')" 0
(error) @user_script: 1: Unknown Redis command called from Lua script
2、脚本执行

Redis Lua脚本可以通过 EVAL 命令或者 EVALSHA 命令执行

EVAL script numkeys [key [key ...]] [arg [arg ...]]
EVALSHA sha1 numkeys [key [key ...]] [arg [arg ...]]
  • numkeys: the number of input key name arguments,keyname的数量
  • key : the name of key,多个keyname空格隔开。在Lua 脚本中通过 KEYS[INDEX]来获取对应的name,其中1 <= INDEX <= numkeys
  • arg : all the keys accessed by the script,多个key空格隔开,在Lua脚本中通过ARGV[INDEX]来获取对应的key,其中1 <= INDEX <= numkeys

EVAL EVALSHA 命令的区别

  • EVAL 命令要求你在每次执行脚本的时候都发送一次脚本主体(script body)。Redis 有一个内部的脚本缓存机制,因此它不会每次都重新编译脚本
  • EVALSHA 命令, Evaluate a script from the server’s cache by its SHA1 digest. 。在执行EVALSHA的时候根据

具体的使用方法如下

使用 EVAL 命令

127.0.0.1:6379> eval "return redis.call('set',KEYS[1],ARGV[1])" 1 username zhangsanOK
127.0.0.1:6379> EVAL "return redis.call('GET', KEYS[1])" 1 username
"zhangsan"

在较新的版本中,lua脚本又新增了许多命令,比如下面的 EVAL_RO,是 EVAL 的一个变种,表示只读,修改数据的命令是不能被执行的

在这里插入图片描述

SCRIPT LOADEVALSHA 命令

使用 SCRIPT LOAD 命令加载lua脚本到服务器脚本缓存中,以达到重复使用,避免多次加载浪费带宽,加载但不会执行这个lua脚本,并返回一个sha校验值。需要配合EVALSHA命令来执行缓存后的脚本

127.0.0.1:6379> SCRIPT LOAD "return 'hello'"
"1b936e3fe509bcbc9cd0664897bbe8fd0cac101b"
127.0.0.1:6379> EVALSHA 1b936e3fe509bcbc9cd0664897bbe8fd0cac101b 0
"hello"

不会经常变动的脚本推荐使用 EVALSHA

官方文档:https://redis.io/docs/latest/commands/?group=scripting

应用场景
  • 事务操作:Lua脚本可以保证一组Redis命令的原子性
springboot实战
实现分布式锁
public String tryLock() {DefaultRedisScript<Long> script = new DefaultRedisScript<>();script.setScriptSource(new ResourceScriptSource(new ClassPathResource("tryLock.lua")));script.setResultType(Long.class);Long state = stringRedisTemplate.execute(script, Lists.newArrayList("lock-good"), "uuid");if (state == 1){log.info("获取锁成功");}else {log.info("获取锁失败");}return "";
}public String releaseLock() {DefaultRedisScript<Boolean> script = new DefaultRedisScript<>();script.setScriptSource(new ResourceScriptSource(new ClassPathResource("releaseLock.lua")));Boolean releaseLock = stringRedisTemplate.execute(script, Lists.newArrayList("lock-good"));if (releaseLock){log.info("释放锁成功");}else {log.info("释放锁失败");}return "";
}

lua脚本

tryLock.lua

local key = KEYS[1];
local value = ARGV[1];
local expireTime = ARGV[2];
if redis.call('SETNX', key, value) == 1 thenreturn redis.call('PEXPIRE', key, expireTime);
elsereturn 0;
end

releaseLock.lua

local key = KEYS[1];
local value = ARGV[1];
if redis.call('GET', key) == value thenredis.call('DEL', key);return true;
elsereturn false;
end
数据更新

update.lua

local key = KEYS[1];
local value = ARGV[1];
local pexpire = ARGV[1];
if redis.call('GET',key) == value thenredis.call('SET', key, value);redis.call('PEXPIRE', key, pexpire)return 1;
elsereturn 0;
end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/619118.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET基于BS的计算机等级考试系统的设计与实现

摘 要 随着计算机技术的发展及计算机的日益普及&#xff0c;基于B/S结构的考试系统与无纸化办公一样已成为大势所趋。论文详细论述了一个基于B/S结构的计算机等级考试系统的设计过程。软件采用ASP.NET 2005作开发平台&#xff0c;C#作编程语言&#xff0c;SQL Server 2005作…

Python进阶编程 --- 2.MySQL、pymysql、PySpark

文章目录 第一章&#xff1a;SQL基础入门1.1 数据库数据库如何存储数据 1.2 数据库和SQL的关系1.3 MySQL版本1.4 命令提示符内使用MySQL1.5 SQL概述1.5.1 SQL语言分类1.5.2 SQL语言特性 1.6 DDL库管理表管理 1.7 DML - 数据操作1.8 DQL - 查询和计算数据1.8.1 基础数据查询1.8.…

《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制空气质量数据平行坐标图

在MATLAB中绘制平行坐标图可以使用parallelcoords函数。平行坐标图通常用于可视化多维数据&#xff0c;特别适用于观察各个维度之间的关系。以下是一个简单的示例&#xff0c;展示如何使用MATLAB创建一个平行坐标图。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/dire…

爬虫 | 网易新闻热点数据的获取与保存

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目是一个简单的网络爬虫&#xff0c;用于从网易新闻的热点新闻列表中提取标题和对应的链接&#xff0c;并将提取到的数据保存到一个 CSV 文件中。 目录 一、技术栈 二、功能说明 三、注意事项 四、代码解析 1. 导入所需…

Python 全栈 Web 应用模板:成熟架构,急速开发 | 开源日报 No.223

tiangolo/full-stack-fastapi-template Stars: 15.6k License: MIT full-stack-fastapi-template 是一个现代化的全栈 Web 应用模板。 使用 FastAPI 构建 Python 后端 API。使用 SQLModel 进行 Python SQL 数据库交互&#xff08;ORM&#xff09;。Pydantic 用于数据验证和设…

Redis入门到通关之List命令

文章目录 ⛄介绍⛄List的常见命令有⛄RedisTemplate API❄️❄️添加缓存❄️❄️将List放入缓存❄️❄️设置过期时间(单独设置)❄️❄️获取List缓存全部内容&#xff08;起始索引&#xff0c;结束索引&#xff09;❄️❄️从左或从右弹出一个元素❄️❄️根据索引查询元素❄…

【OpenHarmony】XTS环境配置

零、参考 1、xts测试环境配置&#xff1a;https://www.yuque.com/u25440504/ehvzki/ik2fso 2、Windows安装Python、pip、easy_install的方法&#xff1a;https://pythonjishu.com/bmxqeisbkzgrpnn/ 3、Python中easy_install 和 pip 的安装及使用&#xff1a; https://blog.c…

网络网络层之(2)ARP协议

网络网络层之(2)ARP协议 Author&#xff1a;Once Day Date: 2024年4月1日 漫漫长路&#xff0c;有人对你笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的博客-CSDN博客。 参考文档: 《TCP/IP详解卷一》arp(8) - Linux manual page (man7.org)彻底搞懂系…

基于RT-Thread(RTT)的BMP280气压计驱动(I2C通信)

前言 本文基于RTT操作系统使用STM32F401RET6驱动BMP280气压计模块&#xff0c;使用I2C协议通信 一、新建工程 二、添加软件包 三、添加这个包 四、打开CubeMX 五、配置时钟源&#xff0c;使用外部晶振 六、配置串行下载口 七、打开I2C&#xff0c;我这里使用的是I2C2&#x…

Abstract Factory抽象工厂模式详解

模式定义 提供一个创建一系列相关或互相依赖对象的接口&#xff0c;而无需指定它们具体的类。 代码示例 public class AbstractFactoryTest {public static void main(String[] args) {IDatabaseUtils iDatabaseUtils new OracleDataBaseUtils();IConnection connection …