Spring Boot 集成Redis 的Lua脚本详解

1. 对比Lua脚本方案与Redis自身事务

对比表格
对比维度 Redis事务(MULTI/EXEC) Lua脚本方案
原子性 事务命令序列化执行,但中间可被其他命令打断,不保证原子性 Lua脚本在Redis单线程中原子执行,不可中断
计算能力 仅支持Redis内置命令,无法复杂计算 支持Lua脚本,可实现复杂逻辑运算
性能 需多次网络交互,性能较低 通过SHA1复用脚本,减少网络传输,性能更高
适用场景 简单命令序列化执行 需要原子性且涉及复杂计算的场景

2. 两种运行Lua脚本的方法示例

方法1:直接发送Lua脚本(不缓存)
lua 复制代码
  
-- Lua脚本:将key1的值加1,并返回新值  
local value = tonumber(redis.call('GET', KEYS[1]))  
redis.call('SET', KEYS[1], value + 1)  
return value + 1  

Java代码:

java 复制代码
  
// 直接执行Lua脚本,每次传递脚本内容  
RedisScript<Long> script = new DefaultRedisScript<>(  
    "local v=tonumber(redis.call('GET', KEYS[1])); " +  
    "redis.call('SET', KEYS[1], v+1); return v+1", Long.class);  
Long result = redisTemplate.execute(  
    script, Arrays.asList("key1"), new Object[]{});  
方法2:先缓存SHA1后调用
lua 复制代码
  
-- 先执行以下脚本缓存到Redis  
// 第一次执行时缓存脚本  
String script = "...(同上)...";  
String sha1 = redisTemplate.execute(new DefaultRedisScript<>(script, Object.class)).getSha();  // 获取SHA1  

// 后续调用时仅传SHA1和参数  
redisTemplate.execute(  
    new DefaultRedisScript<Long>(sha1, Long.class),  
    Arrays.asList("key1"), new Object[]{});  

3. RedisScript接口及子类详解

RedisScript接口方法说明
方法名 作用描述
getSha() 返回脚本的SHA1哈希值(若已缓存)
getArgsCount() 返回脚本需要的参数数量
getNumberParams() 是否需要参数(已废弃,建议用getArgsCount()
getBody() 返回脚本的原始内容(若未缓存)
DefaultRedisScript类
  • 构造方法

    java 复制代码
    new DefaultRedisScript<>(scriptContent, returnType); // 传入脚本内容  
    new DefaultRedisScript<>(sha1, returnType);         // 传入SHA1  
  • 关键方法

    java 复制代码
    // 设置脚本内容  
    script.setScriptText("lua script content");  
    // 设置SHA1(需确保脚本已缓存)  
    script.setSha("computed_sha1");  
    // 设置参数数量  
    script.setArgsCount(2);  

4. RedisTemplate的execute()方法对比

方法1:默认序列化器
java 复制代码
  
// 使用默认序列化器(如StringRedisSerializer)  
public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) { ... }  

// 示例:执行计数器脚本  
RedisScript<Long> script = new DefaultRedisScript<>(  
    "return tonumber(redis.call('INCR', KEYS[1]))", Long.class);  
Long result = redisTemplate.execute(  
    script, Arrays.asList("counter_key"), new Object[]{});  
方法2:自定义序列化器
java 复制代码
  
// 自定义参数和结果的序列化方式  
public <T> T execute(RedisScript<T> script,  
    RedisSerializer<?> argsSerializer,  
    RedisSerializer<T> resultSerializer,  
    List<K> keys, Object... args) { ... }  

// 示例:处理JSON参数和结果  
RedisScript<MyObject> script = ...;  
MyObject result = redisTemplate.execute(  
    script,  
    Jackson2JsonRedisSerializer.class,  // 参数序列化器  
    new Jackson2JsonRedisSerializer<>(MyObject.class), // 结果序列化器  
    Arrays.asList("key"),  
    new MyParamObject() // 自定义参数对象  
);  
对比表格
方法版本 参数序列化器 结果序列化器 适用场景
默认方法 使用RedisTemplate默认配置 使用RedisTemplate默认配置 简单类型(如String、Long)
自定义方法 可指定任意RedisSerializer 可指定任意RedisSerializer 复杂对象(如JSON、POJO)
相关推荐
Java陈序员1 天前
企业级!一个基于 Java 开发的开源 AI 应用开发平台!
spring boot·agent·mcp
杨运交1 天前
[041][公共模块]分布式唯一ID生成器设计与实现:一款灵活可扩展的雪花算法框架
spring boot
用户3074596982072 天前
Redis 延时队列详解
redis
烤代码的吐司君2 天前
Redis 数据结构 ZSet, BIT, HyperLogLog,Geo 空间数据
redis·后端
Flittly2 天前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
Flynt3 天前
从Spring Boot 4.0升到4.1,我在Maven和gRPC上栽了跟头
java·spring boot·后端
掉鱼的猫4 天前
Spring Boot → Solon 注解迁移实战指南:一张对照表说清楚
java·spring boot
leeyi4 天前
Checkpoint 机制:Agent 怎么在断电后接着跑
redis·aigc·agent
人活一口气5 天前
Spring Boot与AIGC的完美结合:从零搭建智能内容生成平台
java·spring boot·aigc
云技纵横5 天前
一个 @Async 让循环依赖暴雷:Spring 代理的暗坑
redis