Reids脚本全解

news/2024/7/24 12:14:46 标签: lua, redis, java

Redis 脚本使用 Lua 解释器来执行脚本,我们一般叫Lua脚本
Redis 2.6 版本通过内嵌支持 Lua 环境

1、为什么要用Lua脚本?

  • 减少网络开销:多次网络请求,可以用一个请求完成,使用脚本,直接放在redis服务器上执行,减少了网络往返时延
  • 原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他进程或者命令插入
  • 复用:客户端发送的脚本会永久存储在Redis中,其他客户端可以直接复用这一脚本

2、如何正确使用?

1)EVAL

执行脚本的命令是 EVAL,基本语法如下:
EVAL script numkeys key [key …] arg [arg …]

在 Lua 脚本中,可以使用两个不同函数来执行 Redis 命令,它们分别是:redis.call()和redis.pcall()

rediscallredispcall_13">2)redis.call()和redis.pcall()区别

两者的区别在于它们对错误处理的不同

  • redis.pcall()出错时不会抛出错误
  • redis.call()会抛出错误

3)编写脚本

我们通过编写两段脚本,来执行下,并验证不同函数

准备测试数据

lua">本地:0>set key1 1
"OK"
本地:0>set key2 2
"OK"
本地:0>set forlan 程序员
"OK"

编写lua脚本,把key1、key2对应的值分别从1、2改成11、22

  • 使用call函数,出现错误
lua">本地:0>eval "redis.call('SET',KEYS[1],ARGV[1]); redis.call('HGET','forlan',ARGV[1]); redis.call('SET',KEYS[2],ARGV[2]);return 1;" 2 key1 key2 11 22
"ERR Error running script (call to f_50eb1c8e04a6356bc813ba70dad327b5be4b0c0c): @user_script:1: WRONGTYPE Operation against a key holding the wrong kind of value "
本地:0>get key1
"11"
本地:0>get key2
"2"
  • 使用pcall函数,未发现异常
lua">本地:0>eval "redis.pcall('SET',KEYS[1],ARGV[1]); redis.pcall('HGET','forlan',ARGV[1]); redis.pcall('SET',KEYS[2],ARGV[2]);return 1;" 2 key1 key2 11 22
"1"
本地:0>get key1
"11"
本地:0>get key2
"22"

小结

我们通过redis.call(‘HGET’,‘forlan’,ARGV[1]);来模拟出错的情况

  • 可以看到使用call函数,key1设置成功,但key2的值没有改变
  • 可以看到使用pcall函数,key1和key2都设置成功了

redis.call()函数会中断Lua脚本的执行,并抛出异常;
redis.pcall()函数不会中断Lua脚本的执行;
所以,为了保证脚本的原子性,要谨慎使用redis.call()函数,我们在代码中使用的话,记得需要捕获异常处理

3、Lua脚本为什么能保证原子性?

官方解答

Atomicity of scripts
Redis uses the same Lua interpreter to run all the commands. Also Redis guarantees that a script is executed in an atomic way: no other script or Redis command will be executed while a script is being executed. This semantic is similar to the one of MULTI / EXEC- From the point of view of all the other clients the effects of a script are either still not visible or already completed

中文意思

Redis使用相同的Lua解释器来运行所有命令。此外,Redis保证脚本以原子方式执行:在执行脚本时,不会执行其他脚本或Redis命令。这个语义类似于MULTI/EXEC的语义-从所有其他客户端的角度来看,脚本的效果要么仍然不可见,要么已经完成

简单理解,就是执行脚本时不会执行其他脚本或Redis命令,类似于给脚本加了锁
虽然脚本的开销很小,但我们使用的时候,注意避免使用慢脚本,以免脚本执行的时候,我们其它redis命令无法执行

4、应用场景

  • 限流
  • 分布式锁
  • 自增id
lua">本地:0>eval " local key = KEYS[1] local id = redis.call('get',key) if(id == false) then redis.call('set',key,1) return 1 else redis.call('set',key,id+1) return id end" 1 forlan
"1"
本地:0>eval " local key = KEYS[1] local id = redis.call('get',key) if(id == false) then redis.call('set',key,1) return 1 else redis.call('set',key,id+1) return id end" 1 forlan
"2"
本地:0>eval " local key = KEYS[1] local id = redis.call('get',key) if(id == false) then redis.call('set',key,1) return 1 else redis.call('set',key,id+1) return id end" 1 forlan
"3"

http://www.niftyadmin.cn/n/176785.html

相关文章

Redis中的Set集合

Set 文章目录Set常用的命令saddsmemberssismemdersremscardsrandmemberspopsmove4.2 集合运算sdiffsunionsintersintercard常用的命令 Set特点:单值多value,value值不能重复 命令作用sadd key member添加smembers key遍历集合中的所有元素sismember ke…

C++面向对象学习

文章目录c 11特性auto和decltype类型识别nullptr引入智能指针lambda函数移动语义内存管理分区虚函数和纯虚函数内存池虚函数继承方法c 11特性 auto和decltype类型识别 auto无法识别const顶层和引用,其他类型可识别。 decltype可识别const顶层和引用,只…

新旧势力抢着上,AVP凭什么成为新卖点?

随着国内汽车保有量的激增,车位稀缺现象愈演愈烈,加上智能化趋势的催化,泊车细分赛道迎来了新风口。 早在2021年1月,搭载百度 AVP 自主泊车方案的威马全新车型 W6,就率先成为了国内具备该功能的消费级车型之一。不管是…

EPICS用户界面Control System Studio

用户接口工具 1) 窗口编辑器/运行时 2)条形图 3)通道访问工具 4)存档系统 5) 警报处理器 6) 对日志本,PV名, ...的站点特定的支持 7)用于Windows, Linux, OSX的集…

Android Studio Logcat使用

先上官方文档 使用Logcat查看日志 当前最新版本的Android Studio,Logcat的风格变了,默认的输出带日期、时间进程和线程 ID、TAG、APP包名、优先级以及消息,几乎占据了屏幕的所有宽度,虽然可以选中Logcat面板左侧的换行按钮&#…

MATLAB | 全网最详细网络图(图论图)绘制教程

一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点,当然图论与网络优化的算法一篇不可能完全讲清楚,未来如果看的人多可以适当更新,同时做部分网络图绘图复刻。 以下是本篇绘图实验效果&#xff1…

TextDynamic检查和PDF引擎进行了一些改进

TextDynamic检查和PDF引擎进行了一些改进 对编辑器、拼写检查和PDF引擎进行了一些改进。 TextDynamic是一种免版税的文字处理和报告控件,可以嵌入到应用程序中,以创建代码中的文本,为最终用户提供所见即所得的编辑功能,并将文档格…

list_for_each 详解

list_for_each 详解 最近在学习linux内核,看到进程管理时,有这么一段代码,一脸懵逼; struct task_struct *task; struct list_head *list; list_for_each(list, &current->children) { task list_entry(list, struct t…