lua redis执行lua脚本


lua redis执行lua脚本

           

redis使用命令行、redis-cli客户端、redisTemplate执行lua脚本

       

              

                                    

命令行、客户端执行脚本

         

语法格式

# 直接执行脚本(redis-cli客户端执行)
eval lua-script key-num [key key2 key3 ...] [value value2 value3 ...] 


# 缓存脚本后执行(命令行执行,没有进入客户端)
redis-cli --eval --lua-script [key key2 ...] , [value value2 ...]
 * key与value用逗号间隔,且逗号前后有空格)

          

lua 调用redis命令

redis.call(command, KEYS[1], KEYS[2], ... , ARGV[1], ARGV[2], ...)

# 命令说明
KEYS[1]:第一个key
ARGV[1]:第一个value
KEYS、ARGV不需要一一对应,个数不需要相等

# 示例
redis.call('set', KEYS[1], ARGV[1])
redis.call('get', KEYS[1])

          

示例:redis-cli客户端执行脚本

huli@hudeMacBook-Pro ~ % docker exec -it redis2 bash

-- redis-cli客户端
root@0d79dbff702e:/data# redis-cli

-- KEYS、ARGV名称是固定的,不能随便设置
127.0.0.1:6379> eval "redis.call('set',key[1],arg[1])" 1 set 瓜田李下
(error) ERR Error running script (call to f_c7f25ef16dd21c6a4dc44cf3964041227459f25e): @enable_strict_lua:15: user_script:1: Script attempted to access nonexistent global variable 'key'

-- set key=瓜田李下
127.0.0.1:6379> eval "redis.call('set',KEYS[1],ARGV[1])" 1 key 瓜田李下
(nil)

-- 获取key:没有return,无返回值
127.0.0.1:6379> eval "redis.call('get',KEYS[1])" 1 key
(nil)

-- 调用return,返回key对用的value(瓜田李下)
-- 由于是中文,redis存储的时候进行了序列化
127.0.0.1:6379> eval "return redis.call('get',KEYS[1])" 1 key
"\xe7\x93\x9c\xe7\x94\xb0\xe6\x9d\x8e\xe4\xb8\x8b"

-- 设置key2=gtlx
127.0.0.1:6379> eval "redis.call('set',KEYS[1],ARGV[1])" 1 key2 gtlx
(nil)

-- 返回key2对应的value(瓜田李下)
127.0.0.1:6379> eval "return redis.call('get',KEYS[1])" 1 key2
"gtlx"

           

示例:命令行执行脚本文件

huli@hudeMacBook-Pro ~ % docker exec -it redis2 bash

-- redis命令行生成脚本文件:test.lua
root@0d79dbff702e:/data# echo "redis.call('set', KEYS[1], ARGV[1]) return redis.call('get',KEYS[1])" > test.lua

-- 查看文件
root@0d79dbff702e:/data# ls
dump.rdb  test.lua
root@0d79dbff702e:/data# cat test.lua
redis.call('set', KEYS[1], ARGV[1]) return redis.call('get',KEYS[1])

-- 命令行执行文件
root@0d79dbff702e:/data# redis-cli --eval test.lua key , gtlx
"gtlx"

          

            

                                    

redisTemplate 执行脚本

         

***********

相关类与接口

       

RedisScript

public interface RedisScript {
    String getSha1();

    @Nullable
    Class getResultType();

    String getScriptAsString();

    default boolean returnsRawValue() {
        return this.getResultType() == null;
    }

    static  RedisScript of(String script) {
        return new DefaultRedisScript(script);
    }

    static  RedisScript of(String script, Class resultType) {
        Assert.notNull(script, "Script must not be null!");
        Assert.notNull(resultType, "ResultType must not be null!");
        return new DefaultRedisScript(script, resultType);
    }

    static  RedisScript of(Resource resource) {
        Assert.notNull(resource, "Resource must not be null!");
        DefaultRedisScript script = new DefaultRedisScript();
        script.setLocation(resource);
        return script;
    }

    static  RedisScript of(Resource resource, Class resultType) {
        Assert.notNull(resource, "Resource must not be null!");
        Assert.notNull(resultType, "ResultType must not be null!");
        DefaultRedisScript script = new DefaultRedisScript();
        script.setResultType(resultType);
        script.setLocation(resource);
        return script;
    }
}

       

DefaultRedisScript

public class DefaultRedisScript implements RedisScript, InitializingBean {
    private final Object shaModifiedMonitor;
    @Nullable
    private ScriptSource scriptSource;
    @Nullable
    private String sha1;
    @Nullable
    private Class resultType;

    public DefaultRedisScript() {
        this.shaModifiedMonitor = new Object();
    }

    public DefaultRedisScript(String script) {
        this(script, (Class)null);
    }

    public DefaultRedisScript(String script, @Nullable Class resultType) {
        this.shaModifiedMonitor = new Object();
        this.setScriptText(script);
        this.resultType = resultType;
    }

    public void afterPropertiesSet() {
        Assert.state(this.scriptSource != null, "Either script, script location, or script source is required");
    }

    public String getSha1() {
        synchronized(this.shaModifiedMonitor) {
            if (this.sha1 == null || this.scriptSource.isModified()) {
                this.sha1 = DigestUtils.sha1DigestAsHex(this.getScriptAsString());
            }

            return this.sha1;
        }
    }

    @Nullable
    public Class getResultType() {
        return this.resultType;
    }

    public String getScriptAsString() {
        try {
            return this.scriptSource.getScriptAsString();
        } catch (IOException var2) {
            throw new ScriptingException("Error reading script text", var2);
        }
    }

    public void setResultType(@Nullable Class resultType) {
        this.resultType = resultType;
    }

    public void setScriptText(String scriptText) {
        this.scriptSource = new StaticScriptSource(scriptText);
    }

    public void setLocation(Resource scriptLocation) {
        this.scriptSource = new ResourceScriptSource(scriptLocation);
    }

    public void setScriptSource(ScriptSource scriptSource) {
        this.scriptSource = scriptSource;
    }
}

         

RedisTemplate:stringRedisTemplate继承了redisTemplate,也可执行lua脚本

public class RedisTemplate extends RedisAccessor implements RedisOperations, BeanClassLoaderAware {

    public  T execute(RedisScript script, List keys, Object... args) {
        return this.scriptExecutor.execute(script, keys, args);
    }

    public  T execute(RedisScript script, RedisSerializer argsSerializer, RedisSerializer resultSerializer, List keys, Object... args) {
        return this.scriptExecutor.execute(script, argsSerializer, resultSerializer, keys, args);
    }

           

***********

示例

       

test.lua

                       lua redis执行lua脚本_第1张图片

redis.call("set",KEYS[1], ARGV[1])
return redis.call("get", KEYS[1])

         

RedisLuaTest

@Component
public class RedisLuaTest {

    @Value("classpath:/lua/test.lua")
    private Resource resource;

    @javax.annotation.Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostConstruct
    public void init(){
        DefaultRedisScript redisScript = new DefaultRedisScript<>();
        redisScript.setLocation(resource);
        redisScript.setResultType(String.class);

        System.out.println("redisScript.getSha1():"+redisScript.getSha1());
        System.out.println("redisScript.getScriptAsString():"+redisScript.getScriptAsString());

        String value = stringRedisTemplate.execute(redisScript, Collections.singletonList("key"), "瓜田李下");
        System.out.println(value);
    }
}

        

控制台输出

2022-06-19 19:50:59.094  INFO 886 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 4 ms. Found 0 Redis repository interfaces.
2022-06-19 19:50:59.378  INFO 886 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-06-19 19:50:59.384  INFO 886 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-06-19 19:50:59.385  INFO 886 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.63]
2022-06-19 19:50:59.468  INFO 886 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-06-19 19:50:59.468  INFO 886 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 850 ms
redisScript.getSha1():6c45d62f3875095a03105f73b04c64e77b17fa1e
redisScript.getScriptAsString():redis.call("set",KEYS[1], ARGV[1])
return redis.call("get", KEYS[1])
瓜田李下
2022-06-19 19:51:00.240  INFO 886 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-06-19 19:51:00.249  INFO 886 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 2.043 seconds (JVM running for 2.604)

         

                 

你可能感兴趣的:(lua,lua)