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)
相关推荐
pjx9874 分钟前
质量的“试金石”:精通Spring Boot单元测试与集成测试
spring boot·spring·单元测试·集成测试
青铜爱码士43 分钟前
redis+lua+固定窗口实现分布式限流
redis·分布式·lua
王景程2 小时前
如何使用 Redis 缓存验证码
redis·缓存·mybatis
编程在手天下我有2 小时前
Redis 常见问题深度剖析与全方位解决方案指南
数据库·redis·缓存·性能优化·数据持久化·分布式系统
呆萌很3 小时前
基于 Spring Boot 瑞吉外卖系统开发(八)
spring boot
JavaDog程序狗3 小时前
【java】easypoi导出excel单元格,填充动态下拉列
java·spring boot·excel
呆萌很4 小时前
基于 Spring Boot 瑞吉外卖系统开发(九)
spring boot
Kings904 小时前
告别手动注入!Bean Assistant插件让SpringBoot开发效率翻倍🚀
spring boot
.生产的驴4 小时前
SpringBoot 接口国际化i18n 多语言返回 中英文切换 全球化 语言切换
java·开发语言·spring boot·后端·前端框架
-曾牛5 小时前
Spring Boot中@RequestParam、@RequestBody、@PathVariable的区别与使用
java·spring boot·后端·intellij-idea·注解·spring boot 注解·混淆用法