发布时间:2025-11-04 07:37:51 来源:云智核 作者:人工智能

Redis中每条命令都是原子性的,即执行结果要么全部成功要么全部失败。脚本在某些业务场景下,中执需要执行多条命令,脚本并且要保证多条命令的中执原子性。这时,脚本如果命令逐条执行,中执显然是脚本不能保证原子性的。有同学可能会想到使用Redis的中执事务功能,事务是脚本可以保证原子性,但是中执受限于命令的功能,有些场景下并不能实现想要的脚本功能。
使用执行Lua脚本的中执方式可以解决以上问题,Lua脚本整体上在Redis中是脚本原子性的。
在Redis中通过EVAL命令来执行Lua脚本,中执基本语法如下:
复制redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]1.参数说明:
script: 参数是一段Lua脚本程序。脚本不必(也不应该)定义为一个 Lua 函数。numkeys: 用于指定键名参数的个数。源码库key [key ...]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。arg [arg ...]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。获取指定key的值,相当于于 GET somekey
复制EVAL "return redis.call(GET, KEYS[1])" 1 somekey1.再看一个LPUSH的例子,相当于 LPUSH somelist 1 2 3
复制EVAL "return redis.call(LPUSH,KEYS[1], ARGV[1], ARGV[2], ARGV[3])" 1 somelist 1 2 31.简单说下Redis执行lua脚本相关的其他几个命令:
EVALSHA命令根据给定的SHA1,执行缓存在服务器中的脚本。SCRIPT EXISTS命令用于检查指定SHA1值对应的脚本是否在Redis缓存中。SCRIPT FLUSH命令用于清除所有的缓存脚本。SCRIPT KILL命令用于杀死当前正在运行的 Lua 脚本,当且仅当这个脚本没有执行过任何写操作时,这个命令才生效。服务器租用这个命令主要用于终止运行时间过长的脚本,比如一个因为 BUG 而发生无限循环的脚本。SCRIPT KILL 执行之后,当前正在运行的脚本会被杀死,执行这个脚本的客户端会从 EVAL 命令的阻塞当中退出,并收到一个错误作为返回值。调用Redis命令,当执行出错时,该方法会直接返回错误,并退出。
复制redis.call(redisCommand, key, argv...)1.调用Redis命令,当执行出错时,记录错误信息,并继续执行。
复制redis.pcall(redisCommand, key, argv...)1.记录日志,写入到Redis配置的日志文件中,日志级别有四种,分别是redis.LOG_DEBUG、redis.LOG_VERBOS、redis.LOG_NOTICE和redis.LOG_WARNING。
复制redis.log(logLevel, message)1.计算输入字符串的sha1哈希值。
复制redis.sha1hex(arvg)1.Redis调用Lua脚本,脚本执行完成后将结果返回给Redis,Redis再将结果返回给客户端。这个过程中会出现Redis执行结果类型到Lua数据类型的高防服务器转换,然后Lua类型到Redis类型的转换。Redis类型到Lua类型转换关系如下:
Redis返回的数据类型
Lua数据类型
integer(整数回复)
number(数字类型)
bulk replay(字符串)
string(字符串类型)
多行字符串
table(数组形式)
status(状态回复)
table(只有一个ok字段的数组)
error(错误回复)
table(只有一个err字段的数组)
Lua类型到Redis类型转换关系如下:
Lua数据类型
Redis返回数据类型
number(数字类型)
integer(整数回复)
string(字符串类型)
bulk replay(字符串)
table(数组形式)
多行字符串
table(只有一个ok字段的数组)
status(状态回复)
table(只有一个err字段的数组)
error(错误回复)