目录
- 前言
- 一、项目准备
- 二、编写 Lua 脚本文件
- 三、加载 Lua 脚本到 Redis
- 四、封装 Lua 脚本调用服务
- 五、创建 REST 接口进行测试
- 六、运行测试
- 1. 启动 Redis 服务
- 2. 启动 Spring Boot 应用
- 3. 测试访问
- 七、注意事项
- 八、进阶建议
- 示例结构图
- 总结
前言
Redis 是一个高性能的内存数据库,广泛用于缓存、计数器、分布式锁等场景。在某些业务中,我们需要对多个 Redis 操作进行原子性处理,以保证数据一致性,这时就可以使用 Redis 提供的 Lua 脚本功能。
Spring Boot 通过 RedisTemplate
对 Redis 进行了良好的封装,也支持我们方便地调用 Lua 脚本。本文将带你一步步实现 Spring Boot 中如何:
- 加载 Lua 脚本
- 调用 Lua 脚本
- 实现一个实际业务逻辑:获取 key,若不存在则设置默认值并返回
一、项目准备
创建 Spring Boot 项目
你可以使用 Spring Initializr 创建一个新项目,选择以下依赖:
- Spring Web
- Spring Data Redis
- Lettuce(Redis 客户端)
或者手动创建 Maven 项目后添加如下依赖:
<!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-startephpr</artifactId> </dependency> <!-- Web 支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Redis 支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- Lettuce 客户端 --> <dependency> <groupId>io.lettuce.core</groupId> <artifactId>lettuce-core</artifactId> <version>6.2.4</version> </dependency>
二、编写 Lua 脚本文件
我们将创建一个简单的 Lua 脚本:如果 key 不存在,则设置默认值;存在则直接返回当前值。
脚本内容:get_or_set_default.lua
路径建议为:src/main/resources/lua/get_or_set_default.lua
-- get_or_set_default.lua local key = KEYS[1] local defaultVal = ARGV[1] local value = redis.call('GET', key) if not value then redis.call('SET', key, defaultVal) value = defaultVal end return value
三、加载 Lua 脚本到 Redis
我们可以利用 Spring 的生命周期回调(如 @PostConstruct
)来加载 Lua 脚本,并保存其 SHA1 校验码,后续通过 EVALSHA
来调用。
创建脚本加载类:LuaScriptLoader.Java
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Service; import javax.anwww.devze.comnotation.PostConstruct; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; @Service public class LuaScriptLoader { private final RedisTemplate<String, Object> redisTemplate; // 存储脚本的 SHA1 值 public static String GET_OR_SET_DEFAULT_SHA; public LuaScriptLoader(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } @PostConstruct public void loadScripts() throws IOException { Path scriptPath = Paths.get("src/main/resources/lua/get_or_set_default.lua"); String scriptContent = Files.readString(scriptPath); DefaultRedisScript<String> redisScript = new DefaultRedisScript<>(); redisScript.setScriptText(scriptContent); redisScript.setResultType(String.class); // 执行 SCRIPT LOAD 命令加载脚本 GET_OR_SET_DEFAULT_SHA = redisTemplate.execute( redisScript, Collections.singletonList("dummyKey"), "defaultValue" ); System.out.println("Lua Script SHA1: " + GET_OR_SET_DEFAULT_SHA); } }
注意:
- 我们使用了一个 dummyKey 和 dummyValue 来执行一次脚本,只是为了触发脚本加载。
- 实际调用时使用的是
EVALSHA
命令。
四、封装 Lua 脚本调用服务
我们创建一个服务类来封装 Lua 脚本的调用逻辑。
创建服务类:RedisLuaService.java
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.Collections; @Service public class RedisLuaService { private final RedisTemplate<String, Object> redisTemplate; public RedisLuaService(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } /** * 调用 Lua 脚本:根据 key 获取值,若不存在则设置默认值并返回 */ public String getOrSetDefault(String key, String defaultValue) { return (String) redisTemplate.execute( LuaScriptLoader.GET_OR_SET_DEFAULT_SHA, Collections.singletonList(key), defaultValue ); } }
五、创建 REST 接口进行测试
为了方便测试,我们创建一个简单的接口。
创建控制器类:RedisLuaController.java
import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/redis") public class RedisLuaController { private final RedisLuaService redisLuaService; public RedisLuaController(RedisLuaService redisLvIutaSsPuaService) { this.redisLuaService = redisLuaService; } @GetMapping("/get-or-set") public String getOrDefault( @RequestParam String key, @RequestParam(required = false, defaultValue = "default_value") String defaultValue) { return redisLuaService.getOrSetDefault(key, defaultValue); } }
六、运行测试
1. 启动 Redis 服务
确保你本地或服务器上已经启动了 Redis:
redis-server
2. 启动 Spring Boot 应用
使用 IDE 或命令行启动 Spring Boot 项目:
mvn spring-boot:run
3. 测试访问
访问如下 URL:
http://localhost:8080/redis/get-or-set?key=test_lua&defaultValue=hello_redis
第一次请求:
Redis 中没有 test_lua
键,会自动设置为 hello_redis
,并返回该值。
第二次请求:
即使不传 defaultValue
,也会返回 hello_redis
,因为键已存在。
七、注意事项
项目 | 说明 |
---|---|
脚本缓存 | Redis 会缓存加载过的 Lua 脚本,但重启后失效,需重新加载 |
调试困难 | Lua 脚本不能输出日志,建议先在 Redis CLI 中测试后再集成 |
性能考量 | Lua 脚本是单线程执行的,避免复杂运算 |
异常处理 | 在 Java 层应对脚本执行失败做容错处理 |
参数传递 | KEYS 是数组,ARGV 是参数数组,顺序要对应 |
八、进阶建议
- 将所有 Lua 脚本统一管理,使用配置中心或数据库存储
- 结合 AOP 或拦截器,实现 Lua 脚本调用的自动重试机制
- 使用 Redisson 等高级库简化 Lua 脚本操作
- 使用 Springjavascript Cache 抽象层结合 Lua 脚本实现更复杂的缓存策略
示例结构图
src/
├── main/│ ├── java/│ │ └── com.example.demo/│ │ ├── DemoApplication.java│ │ ├── service/│ │ │ ├── RedisLuaService.java│ │ │ └── LuaScriptLoader.java│ │ └── controller/│ │ └── RedisLuaController.java│ └── resources/│ └── lua/│ └── get_or_set_default.lua└── pom.XML
总结
本文详细介绍了如何在 Spring Boot 中调用 Redis 的 Lua 脚本,包括:
- 添加必要的依赖
- 编写 Lua 脚本
- 使用
RedisTemplate
加载和调用脚本 - 构建完整的调用流程与接口测试
Lua 脚本非常适合用来实现一些需要原子性的 Redis 操作,是构建高并发系统的重要工具之一。
到此这篇关于SpringBphpoot集成Redis并调用Lua脚本的示例详解的文章就介绍到这了,更多相关SpringBoot集成Redis调用Lua内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论