spring data redis 执行 lua 脚本

使用Spring Data Redis的Lua脚本功能,通过keys模式匹配获取所有匹配的key,并统计这些key作为Sorted Set时的元素总数。

需求:通过keys pattern 来找到匹配的所有的key,并且循环搞些事情

spring data里面直接提供了redis lua脚本的抽象接口RedisScript和默认实现类,直接用就可以


代码如下:

        Long result = 0L;

        StringBuilder sb = new StringBuilder();
        sb.append(" local keylist = redis.call('keys',KEYS[1])");
        sb.append(" local num = 0");
        sb.append(" for i,v in ipairs(keylist) do");
        sb.append("     num = num +  redis.call('zcard',v)");
        sb.append(" end");
        sb.append(" return num");

        List<String> keys = new ArrayList<>();
        keys.add("test"+ "*" + "1");

        try {
            RedisScript<Long> luaScript = new DefaultRedisScript<>(sb.toString(), Long.class);
            result = this.execute(luaScript, keys);
        } catch (Exception e) {
            // do nothing
        }
        return result;

这样就可以得到所有的key名字叫"test"+中间任何匹配字段+“1”的 key 的元素个数。(这里没进行类型判断,应该要判断类型的,这里默认test*1的key为zset)

其中KEYS[1] 就是keys数组传进的key,还可以传别的参数,具体可以看execute的参数列表

Spring Boot项目中使用RedisLua脚本可以提升性能和扩展功能。以下是相关示例及使用方法: ### 环境配置 在`application.properties`或`application.yml`中配置Redis连接属性,示例如下: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password=yourPassword ``` 上述配置指定了Redis的主机、端口和密码 [^3]。 ### 引入依赖 可以使用Jedis或Lettuce作为Redis客户端,以下是使用Lettuce客户端的Maven依赖示例: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </dependency> ``` ### 创建Lua脚本 例如创建一个将指定键的值加1并返回新值的Lua脚本: ```lua local value = tonumber(redis.call('GET', KEYS[1])) redis.call('SET', KEYS[1], value + 1) return value + 1 ``` 此脚本先获取指定键的值,将其转换为数字类型,然后加1并重新设置该键的值,最后返回新值 [^4]。 ### 执行Lua脚本的方式 #### 1. 使用`RedisTemplate.execute(RedisScript script, List<K> keys, Object... args)` ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.RedisScript; import org.springframework.stereotype.Service; import java.util.Collections; @Service public class RedisLuaService { @Autowired private RedisTemplate<String, String> redisTemplate; public Long executeLuaScript() { String script = "local value = tonumber(redis.call('GET', KEYS[1])) redis.call('SET', KEYS[1], value + 1) return value + 1"; RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class); String key = "testKey"; return redisTemplate.execute(redisScript, Collections.singletonList(key)); } } ``` #### 2. 使用`RedisScriptingCommands.eval(String script, ReturnType returnType, int numKeys, byte[]... keysAndArgs)` ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisScriptingCommands; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.Collections; @Service public class RedisLuaService2 { @Autowired private RedisTemplate<String, String> redisTemplate; public Long executeLuaScript2() { String script = "local value = tonumber(redis.call('GET', KEYS[1])) redis.call('SET', KEYS[1], value + 1) return value + 1"; RedisConnection connection = redisTemplate.getConnectionFactory().getConnection(); RedisScriptingCommands scriptingCommands = connection.scriptingCommands(); byte[] scriptBytes = script.getBytes(); byte[] keyBytes = "testKey".getBytes(); return (Long) scriptingCommands.eval(scriptBytes, org.springframework.data.redis.connection.ReturnType.INTEGER, 1, keyBytes); } } ``` ### 对比Redis事务与Lua脚本 |对比维度|Redis事务(MULTI/EXEC)|Lua脚本方案| | ---- | ---- | ---- | |原子性|事务命令序列化执行,但中间可被其他命令打断,不保证原子性|Lua脚本Redis单线程中原子执行,不可中断| |计算能力|仅支持Redis内置命令,无法复杂计算|支持Lua脚本,可实现复杂逻辑运算| |性能|需多次网络交互,性能较低|通过SHA1复用脚本,减少网络传输,性能更高| |适用场景|简单命令序列化执行|需要原子性且涉及复杂计算的场景| [^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值