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)
相关推荐
派大鑫wink2 小时前
【JAVA学习日志】SpringBoot 参数配置:从基础到实战,解锁灵活配置新姿势
java·spring boot·后端
xUxIAOrUIII2 小时前
【Spring Boot】控制器Controller方法
java·spring boot·后端
Dolphin_Home2 小时前
从理论到实战:图结构在仓库关联业务中的落地(小白→中级,附完整代码)
java·spring boot·后端·spring cloud·database·广度优先·图搜索算法
JIngJaneIL3 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
廋到被风吹走4 小时前
【数据库】【Redis】定位、优势、场景与持久化机制解析
数据库·redis·缓存
全靠bug跑4 小时前
Spring Cloud OpenFeign 实战三部曲:快速集成 · 连接池优化 · 客户端抽取
java·spring boot·openfeign
北城以北88885 小时前
Spring定时任务与Spring MVC拦截器
spring boot·spring·mvc
缘不易5 小时前
Springboot 整合JustAuth实现gitee授权登录
spring boot·后端·gitee
Mr.朱鹏5 小时前
SQL深度分页问题案例实战
java·数据库·spring boot·sql·spring·spring cloud·kafka
白宇横流学长6 小时前
基于SpringBoot实现的冬奥会科普平台设计与实现【源码+文档】
java·spring boot·后端