redis lua脚本使用说明


redis lua脚本

 

作用:使用lua脚本可将多条命令原子执行,可实现比redis事务更为强大的功能

注意:lua执行过程中,如果出错,已经执行的命令不会回滚

 

 

*********************

相关类与接口

 

RedisTemplate

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {

    @Nullable
    private ScriptExecutor<K> scriptExecutor;

    ...


************
构造方法

    public RedisTemplate() {
    }

    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        boolean defaultUsed = false;
        if (this.defaultSerializer == null) {
            this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
        }

        if (this.enableDefaultSerializer) {
            if (this.keySerializer == null) {
                this.keySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.valueSerializer == null) {
                this.valueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashKeySerializer == null) {
                this.hashKeySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashValueSerializer == null) {
                this.hashValueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }
        }

        if (this.enableDefaultSerializer && defaultUsed) {
            Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
        }

        if (this.scriptExecutor == null) {
            this.scriptExecutor = new DefaultScriptExecutor(this);
        }                        //默认使用DefaultScriptorExecutor执行脚本

        this.initialized = true;
    }


************
执行脚本相关方法

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

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

    。。。。

}

 

 

RedisScript:redis脚本

public interface RedisScript<T> {
    String getSha1();

    @Nullable
    Class<T> getResultType();

    String getScriptAsString();

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

    static <T> RedisScript<T> of(String script) {
        return new DefaultRedisScript(script);
    }//构造RedisScript,无返回值

    static <T> RedisScript of(String script, Class<T> resultType) {
        Assert.notNull(script, "Script must not be null!");
        Assert.notNull(resultType, "ResultType must not be null!");
        return new DefaultRedisScript(script, resultType);
    }//构造RedisScript,返回值得类型为resultType

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

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

 

DefaultRedisScript

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


***********
构造方法

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

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

    public DefaultRedisScript(String script, @Nullable Class<T> 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;
        }
    }//获取脚本的sha1值

    @Nullable
    public Class<T> getResultType() {
        return this.resultType;
    }//获得脚本的返回结果类型

    public String getScriptAsString() {
        try {
            return this.scriptSource.getScriptAsString();
        } catch (IOException var2) {
            throw new ScriptingException("Error reading script text", var2);
        }
    }//获得脚本内容,以string形式返回

    public void setResultType(@Nullable Class<T> 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;
    }
}

 

 

ScriptExecutor:脚本执行接口

public interface ScriptExecutor<K> {
    <T> T execute(RedisScript<T> var1, List<K> var2, Object... var3);

    <T> T execute(RedisScript<T> var1, RedisSerializer<?> var2, RedisSerializer<T> var3, List<K> var4, Object... var5);
}

 

DefaultScriptExecutor

public class DefaultScriptExecutor<K> implements ScriptExecutor<K> {
    private final RedisTemplate<K, ?> template;


********
构造方法

    public DefaultScriptExecutor(RedisTemplate<K, ?> template) {
        this.template = template;
    }


********
普通方法

    public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
        return this.execute(script, this.template.getValueSerializer(), this.template.getValueSerializer(), keys, args);
    }//默认使用redisTemplate的value序列化器序列化传递给脚本的args、反序列化返回结果

    public <T> T execute(RedisScript<T> script, RedisSerializer<?> argsSerializer, RedisSerializer<T> resultSerializer, List<K> keys, Object... args) {
        return this.template.execute((connection) -> {
            ReturnType returnType = ReturnType.fromJavaType(script.getResultType());
            byte[][] keysAndArgs = this.keysAndArgs(argsSerializer, keys, args);
            int keySize = keys != null ? keys.size() : 0;
            if (!connection.isPipelined() && !connection.isQueueing()) {
                return this.eval(connection, script, returnType, keySize, keysAndArgs, resultSerializer);
            } else {
                connection.eval(this.scriptBytes(script), returnType, keySize, keysAndArgs);
                return null;
            }
        });
    }//统一调用脚本的接口,使用argsSerializer序列化args、resultSerializer序列化返回结果

    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 var9) {
            if (!ScriptUtils.exceptionContainsNoScriptError(var9)) {
                throw var9 instanceof RuntimeException ? (RuntimeException)var9 : new RedisSystemException(var9.getMessage(), var9);
            }

            result = connection.eval(this.scriptBytes(script), returnType, numKeys, keysAndArgs);
        }

        return script.getResultType() == null ? null : this.deserializeResult(resultSerializer, result);
    }//底层具体执行脚本的方法

   protected byte[][] keysAndArgs(RedisSerializer argsSerializer, List<K> keys, Object[] args) {
        int keySize = keys != null ? keys.size() : 0;
        byte[][] keysAndArgs = new byte[args.length + keySize][];
        int i = 0;
        if (keys != null) {
            Iterator var7 = keys.iterator();

            label42:
            while(true) {
                while(true) {
                    if (!var7.hasNext()) {
                        break label42;
                    }

                    K key = var7.next();
                    if (this.keySerializer() == null && key instanceof byte[]) {
                        keysAndArgs[i++] = (byte[])((byte[])key);
                    } else {
                        keysAndArgs[i++] = this.keySerializer().serialize(key);
                    }
                }
            }
        }

        Object[] var11 = args;
        int var12 = args.length;

        for(int var9 = 0; var9 < var12; ++var9) {
            Object arg = var11[var9];
            if (argsSerializer == null && arg instanceof byte[]) {
                keysAndArgs[i++] = (byte[])((byte[])arg);
            } else {
                keysAndArgs[i++] = argsSerializer.serialize(arg);
            }
        }

        return keysAndArgs;
    }//将keys、args转换为字节数组,keys用redisTemplate的键序列化器序列化、args用argsSerializer序列化器序列化

    protected byte[] scriptBytes(RedisScript<?> script) {
        return this.template.getStringSerializer().serialize(script.getScriptAsString());
    }//将脚本转换为字节数组

    protected <T> T deserializeResult(RedisSerializer<T> resultSerializer, Object result) {
        return ScriptUtils.deserializeResult(resultSerializer, result);
    }//将脚本的返回结果反序列化

    protected RedisSerializer keySerializer() {
        return this.template.getKeySerializer();
    }//获得redisTemplate键的序列化器

}

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java Redis Lua脚本使用是指在Java应用程序中使用Redis数据库的Lua脚本Lua脚本是一种轻量级的脚本语言,可以在Redis中执行。Java应用程序可以使用Redis的Java客户端库来执行Lua脚本,以实现一些高级功能,如原子性操作、复杂的数据结构和事务处理等。Lua脚本可以在Redis中执行,因此可以利用Redis的高性能和可扩展性来处理大量数据。Java Redis Lua脚本使用是一种非常强大的技术,可以帮助开发人员更好地管理和处理Redis数据库中的数据。 ### 回答2: Java、RedisLua脚本都是非常常见的技术,都有各自的特点和用途。下面让我们一起来介绍一下它们的使用。 Java是一种非常流行的面向对象编程语言,广泛应用于企业级软件开发和Web开发。在Java中,我们可以使用Redis的Java客户端Jedis来连接、操作Redis数据库。 Redis是一个流行的开源内存数据库,提供了高效的数据缓存和查询功能。使用Redis可以将数据缓存在内存中,大大提高了数据读取和写入的速度。在Java中,我们可以使用Jedis连接Redis数据库,并通过Java代码完成对Redis的操作,如设置键值对、获取键值对、删除键值对等等。 Lua是一个快速、轻量级的脚本语言,广泛应用于游戏开发、Web开发、数据处理等领域。在Redis中,我们可以使用Lua脚本来完成复杂的数据处理操作,如统计数据、排序、聚合等等。使用Lua脚本可以大大提高数据处理的效率和准确性。在Java中,我们可以使用Jedis连接Redis数据库,并通过Java代码执行Lua脚本。 总而言之,在Java中,我们可以结合RedisLua脚本,来完成高效的数据处理和操作。我们可以先使用Java代码连接Redis数据库,然后通过Redis提供的Java客户端Jedis来操作Redis数据库。如果需要进行复杂的数据处理,我们可以使用Lua脚本来实现。这种方式可以提高数据处理的效率和可靠性,让我们在Java开发中更加快速便捷地完成数据处理任务。 ### 回答3: Java、RedisLua脚本使用 Java是一种非常流行的编程语言,广泛应用于企业级应用程序的开发中,具有跨平台、高效和安全等特点。Redis是一个高性能键值存储数据库,常用于缓存、Session管理和消息队列等应用场景。Lua是一种轻量级的脚本语言,可用作Redis中的脚本语言,在Redis服务器内部执行,使得Redis具有更强大的功能和更高的性能。 Java可以通过Jedis等Redis客户端库来连接Redis,并对Redis进行数据操作,如存储、读取、更新和删除等。同时,Java也可以通过调用Redis支持的Lua脚本来增强Redis的功能,如实现复杂的数据操作、高级计算和业务逻辑等。Lua脚本可以直接调用Redis的命令和API,也可以通过Jedis提供的API调用Redis。在使用Java调用Lua脚本时,通常将Lua脚本放在Java项目中,然后通过Jedis将脚本加载到Redis中。这样可以避免在Redis中频繁调用外部脚本,提高性能和安全性。 Redis中的Lua脚本通常存储在脚本缓存中,这样可以避免每次调用脚本时都重新装载脚本Lua脚本Redis中的执行是原子操作,这意味着在执行期间,Redis不会执行其他命令或操作。因此,使用Lua脚本可以实现复杂的数据操作和业务逻辑,并保证数据的一致性。 由于Redis支持使用Lua脚本来实现一些原子性的操作,因此,使用Lua脚本可以提高Redis的执行效率,减少客户端和服务器之间的通信和数据传输量。同时,使用Lua脚本也可以提高Redis的安全性,防止因分布式环境下的竞态条件而造成的数据混乱和错误。 综上所述,Java、RedisLua脚本是一些非常强大的技术,可以使得企业级应用程序具有更高的性能、更好的业务逻辑和更强的安全性。因此,在开发企业级应用程序时,需要充分利用这些技术来实现业务需求和优化性能等目标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值