美文网首页
在spring-data-redis中使用lua脚本

在spring-data-redis中使用lua脚本

作者: 人呆木水 | 来源:发表于2017-01-10 18:36 被阅读3789次

参考

Lua 脚本
Programming in Lua

api

  • 使用 RedisScript<T>
  • 使用 RedisTemplate.execute(RedisScript<T> script, List<K> keys, Object... args)

几点需要关注的地方

redisScript.resultType

事实上, DefaultScriptExecutor 拿到 connection.eval 的返回结果后, 只是判断 redisScript.resultType 是否为空,为空则直接返回为空,
如果不为空, 则根据 返回结果是 byte[] 还是 list 调用反序列化函数进行反序列化。

    protected <T> T eval(RedisConnection connection, RedisScript<T> script, ReturnType returnType, int numKeys,
                byte[][] keysAndArgs, RedisSerializer<T> resultSerializer) {
    
            Object result;
            try {
                result = connection.evalSha(script.getSha1(), returnType, numKeys, keysAndArgs);
            } catch (Exception e) {
    
                if (!exceptionContainsNoScriptError(e)) {
                    throw e instanceof RuntimeException ? (RuntimeException) e : new RedisSystemException(e.getMessage(), e);
                }
    
                result = connection.eval(scriptBytes(script), returnType, numKeys, keysAndArgs);
            }
    
            if (script.getResultType() == null) {
                return null;
            }
    
            return deserializeResult(resultSerializer, result);
    }
        
    ....
    
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected <T> T deserializeResult(RedisSerializer<T> resultSerializer, Object result) {
        if (result instanceof byte[]) {
            if (resultSerializer == null) {
                return (T) result;
            }
            return resultSerializer.deserialize((byte[]) result);
        }
        if (result instanceof List) {
            List results = new ArrayList();
            for (Object obj : (List) result) {
                results.add(deserializeResult(resultSerializer, obj));
            }
            return (T) results;
        }
        return (T) result;
    }
    

而序列化工具类则是调用 RedisTemplate

public <T> T execute(final RedisScript<T> script, final List<K> keys, final Object... args) {
        // use the Template's value serializer for args and result
        return execute(script, template.getValueSerializer(), (RedisSerializer<T>) template.getValueSerializer(), keys,
                args);
}
返回值

redis 的返回值里, 只有 byte[] 字节, 或者 list<byte[]> 的我值数据, 所以不要写以下的代码
foo 下的数据不会返回.

local result = { foo = "name", "breaker", "time" }
return result

关于参数


    @SuppressWarnings("unchecked")
    public <T> T execute(final RedisScript<T> script, final List<K> keys, final Object... args) {
        // use the Template's value serializer for args and result
        return execute(script, template.getValueSerializer(), (RedisSerializer<T>) template.getValueSerializer(), keys,
                args);
    }
    
    ... 
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected byte[][] keysAndArgs(RedisSerializer argsSerializer, List<K> keys, Object[] args) {
        final int keySize = keys != null ? keys.size() : 0;
        byte[][] keysAndArgs = new byte[args.length + keySize][];
        int i = 0;
        if (keys != null) {
            for (K key : keys) {
                if (keySerializer() == null && key instanceof byte[]) {
                    keysAndArgs[i++] = (byte[]) key;
                } else {
                    keysAndArgs[i++] = keySerializer().serialize(key);
                }
            }
        }
        for (Object arg : args) {
            if (argsSerializer == null && arg instanceof byte[]) {
                keysAndArgs[i++] = (byte[]) arg;
            } else {
                keysAndArgs[i++] = argsSerializer.serialize(arg);
            }
        }
        return keysAndArgs;
    }

显然, key 与 args 都是有使用 redisTemplate 序列化进行处理.

关于多个序列化工具的问题,

有时候,我们想对key 与值采用不同的序列化工具, 如 key , 使用 string 序列化, value 使用 json 序列化, 从代码上看, 需要重写
redisTemplate

另外, 如果想在 lua 脚本中使用 json, 可以使用全局变量 cjson


local value = { true, { foo = 'mindasset', joo = 'java' } }
local json_text = cjson.encode(value)

return json_text

相关文章

  • Redis学习笔记-Lua脚本

    前言 Redis在2.6版推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。 在Lua脚本中可...

  • Redis中调用Lua脚本阻塞

    在高并发系统中,redis的使用会比较频繁,lua脚本让redis的使用更加灵活。redis中使用lua脚本的好处...

  • 在spring-data-redis中使用lua脚本

    参考 Lua 脚本Programming in Lua api 使用 RedisScript 使用 Redi...

  • SpringBoot在Redis中执行Lua脚本

    SpringBoot执行Lua脚本 之前基本上完成了Lua脚本在Redis中使用的常用方式以及常用指令,在项目使用...

  • 《redis学习》之lua

    Redis+Lua的好处 redis在2.6开始加入了lua脚本,使用lua脚本有如下好处: 减少网络开销。复合操...

  • Redis 脚本

    Redis 脚本 Redis 脚本使用 Lua 解释器来执行脚本。 Reids 2.6 版本通过内嵌支持 Lua ...

  • lua脚本

    lua脚本 执行方法下载lua 打开cmd 或者命令界面 执行lua使用lua 文件

  • springboot中redis的使用(三)

    接上一次springboot中redis的使用(二) Redis脚本的使用步骤 写Lua脚本, 放在Resourc...

  • Redis学习之路(8)命令 -Redis 脚本

    Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常...

  • 17 Redis脚本

    Redis 脚本使用 Lua 解释器来执行脚本。 Reids 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常...

网友评论

      本文标题:在spring-data-redis中使用lua脚本

      本文链接:https://www.haomeiwen.com/subject/hwflbttx.html