1.介绍
redis自从2.6.0版本起就采用内置的Lua解释器通过EVAL命令去执行脚本
EVAL命令首个参数是一个Lua 5.1版本的脚本,这个脚本并不需要定义一个Lua函数或者说是不应该这样做。它可以仅仅是一个Lua语法,这个语法运行在redis服务器上下文
EVAL命令第二参数是代表Redis键的数量,Lua采用基于数组形式(KEYS全局变量)访问这些参数(KEYS[1]、KEYS[2] …)
初次之外的其他参数并不代表redis键,它们可以通过ARGV全部变量定义的数组访问,与KEYS数组设置类似,形式为 ARGV[1]、ARGV[2] …
Redis控制台执行eval命令验证上述描述内容,如下:
> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"
2.lua脚本中调用redis命令
Lua脚本中调用redis命令可以使用2个函数,如下:
- redis.call()
- redis.pcall()
redis.call()与redis.pcall()相似,二者唯一不同之处在于如果执行的redis命令执行失败,redis.call()将产生一个Lua error,从而迫使EVAL命令返回一个错误给命令的调用者,然而redis.pcall()将会捕捉这个错误,并返回代表这个错误的Lua表。
redis.call()和redis.pcall()命令参数是一个格式化后的redis命令,如下:
> eval "return redis.call('set','foo','bar')" 0
OK
上述eval命令执行脚本:设置key=foo,对应value=bar,但是它违背了EVAL命令的语法,因为Lua脚本中使用所有的键都应当使用KEYS数组动态赋值,上述脚本调整如下:
> eval "return redis.call('set',KEYS[1],'bar')" 1 foo
OK
3.Jedis提供eval命令
public Object eval(String script, int keyCount, String... params) {
client.setTimeoutInfinite();
try {
client.eval(script, keyCount, params);
return getEvalResult();
} finally {
client.rollbackTimeout();
}
}
public Object eval(String script, List<String> keys, List<String> args) {
return eval(script, keys.size(), getParams(keys, args));
}