redis中使用lua脚本

前言

redis作为一种key-value的缓存中间件,支持字符串,哈希,集合,有序集合等结构,每种结构都只支持比较简单的命令,这就决定了redis自身不支持复杂的业务运算,但redis支持lua脚本,可以通过lua脚本原子性地完成一些复杂的业务逻辑。

java中运行lua脚本

java中运行lua脚本比较简单,如下

public <T> T runLua(String fileClasspath, Class<T> returnType, List<String> keys, Object ... values){
        DefaultRedisScript<T> redisScript =new DefaultRedisScript<>();
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource(fileClasspath)));
        redisScript.setResultType(returnType);
        return redisTemplate.execute(redisScript,keys,values);
    }

第一个参数是lua脚本的路径,一般lua脚本写成文件的形式比较合适。

第二个参数是返回类型,返回类型一般是string或者list类型。

第三个参数是key列表,如果在Cluster集群中,列表中的key如果分布在不同的节点上会出错,为了避免这个问题,需要在同一节点的keys都加上标志,如key1{me},key2{me}

第四个参数是参数列表。

lua脚本

lua脚本是如何获取入参的,它是通过KEYS[1],ARGV[1]....下标从1开始。

那么又是如果返回结果的,它是通过return语法返回的,一般是字符串或者table类型,table对应java中的list类型。

可以看看下面脚本,逻辑比较简单,遍历key中的所有值,返回符合条件的列表。

local result={};
local key=KEYS[1];
local value=ARGV[1];
 
local list =redis.call("hkeys",key);
 
for i,v in ipairs(list) do
 local val= redis.call("hget",key,v);
 if(tonumber(val)<tonumber(value)) then
  table.insert(result,1,v);
 end
end
 
return result;

redis命令

从上面的脚本可以看到,lua脚本里面是通过redis.call("command",key,argv.....)的形式执行redis命令的,而命令繁多,这里不一一叙述,可以看教程 https://www.runoob.com/redis/redis-commands.html

lua语法

lua也有自身的语法和数据类型,具体可以看 https://www.runoob.com/lua/lua-basic-syntax.html

小结

lua脚本使用上比较简单,但是要注意性能,不能执行太复杂的运算,在redis中的操作都是单线程的,如果执行太慢,会阻塞其他请求的,如果在lua中写一个死循环,那就完了。