Redis使用Lua脚本
约 633 字大约 2 分钟
2025-01-31
1.前言
Lua 是一门古老的语言。由于Redis的单个命令都是原子性,但是有时候我们希望能够组合多个Redis命令,并让这个组合也能够 原子性 的执行
2.简单语法
Lua的几个常用的数据类型如下:
- nil:空
- boolean:布尔值
- number:数字
- string:字符串
- table:表
2.1 声明类型
--- 全局变量
name = 'hello'
--- 局部变量,使用local关键字
local age = 18
2.2 判断
local a = 10
if a < 10 then
print('a小于10')
elseif a < 20 then
print('a小于20,大于等于10')
else
print('a大于等于20')
end
3.Redis使用Lua
3.1 EVAL命令
EVAL luascript numkeys key arg
EVAL
: 命令的关键字luascript
:Lua 脚本numkeys
:指定的Lua脚本需要处理键的数量,其实就是key
数组的长度key
:传递给Lua脚本零到多个键,空格隔开,在Lua 脚本中通过KEYS[INDEX]
来获取对应的值,其中1 <= INDEX <= numkeys
arg
:是传递给脚本的零到多个附加参数,空格隔开,在Lua脚本中通过ARGV[INDEX]
来获取对应的值,其中1 <= INDEX <= numkeys
3.2 举例
3.2.1 设置和获取 Redis 值
EVAL "redis.call('set', KEYS[1], ARGV[1])" 1 mykey myvalue
mykey
:Redis 中的键myvalue
:键对应的值- 命令作用:将
mykey
的值设置为myvalue
3.2.2 增量操作
EVAL "return redis.call('incr', KEYS[1])" 1 counter
redis.call('incr', KEYS[1])
:调用 Redis 的INCR
命令,对指定键的值进行递增1
:表示脚本后面有 1 个键(counter
)counter
:这是我们想要递增的 Redis 键
注意:如果 counter
键在 Redis 中不存在,INCR
会将它初始化为 0,然后递增 1
3.2.3 检查并设置键值
EVAL "if redis.call('exists', KEYS[1]) == 0 then redis.call('set', KEYS[1], ARGV[1]) end" 1 mykey myvalue
redis.call('exists', KEYS[1])
:检查键mykey
是否存在- 如果
mykey
不存在,则执行set
命令,将mykey
设置为myvalue
- 这条命令确保只有在
mykey
不存在时,才会执行SET
操作
4.SpringBoot使用Redis和Lua
用 Lua 脚本检查并设置一个值
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
public String executeLuaScript() {
// Lua脚本: 如果key存在,返回"exists",否则设置它的值并返回"set"
String luaScript = "if redis.call('exists', KEYS[1]) == 1 then " +
" return 'exists'; " +
"else " +
" redis.call('set', KEYS[1], ARGV[1]); " +
" return 'set'; " +
"end";
// 创建DefaultRedisScript对象
DefaultRedisScript<String> redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(luaScript); // 设置脚本
redisScript.setResultType(String.class); // 设置返回值类型
// 执行脚本
String result = redisTemplate.execute(redisScript, Collections.singletonList("myKey"), "myValue");
return result; // 返回执行结果
}
}