java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot集成Redis调用Lua

SpringBoot集成Redis并调用Lua脚本的示例详解

作者:超级小忍

Redis 是一个高性能的内存数据库,广泛用于缓存、计数器、分布式锁等场景,本文主要和大家详细介绍了SpringBoot如何集成Redis并调用Lua脚本,需要的小伙伴可以了解下

前言

Redis 是一个高性能的内存数据库,广泛用于缓存、计数器、分布式锁等场景。在某些业务中,我们需要对多个 Redis 操作进行原子性处理,以保证数据一致性,这时就可以使用 Redis 提供的 Lua 脚本功能。

Spring Boot 通过 RedisTemplate 对 Redis 进行了良好的封装,也支持我们方便地调用 Lua 脚本。本文将带你一步步实现 Spring Boot 中如何:

一、项目准备

创建 Spring Boot 项目

你可以使用 Spring Initializr 创建一个新项目,选择以下依赖:

或者手动创建 Maven 项目后添加如下依赖:

<!-- Spring Boot Starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</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.annotation.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);
    }
}

注意:

四、封装 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 redisLuaService) {
        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 是参数数组,顺序要对应

八、进阶建议

示例结构图

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 脚本非常适合用来实现一些需要原子性的 Redis 操作,是构建高并发系统的重要工具之一。

到此这篇关于SpringBoot集成Redis并调用Lua脚本的示例详解的文章就介绍到这了,更多相关SpringBoot集成Redis调用Lua内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文