Java使用lua案例

导入依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
</dependency>

代码案例

import redis.clients.jedis.Jedis;

public class RedisLuaDemo {
    private Jedis jedis;

    public RedisLuaDemo(String host, int port) {
        this.jedis = new Jedis(host, port);
    }

    public boolean decrement(String key) {
        String luaScript =
            "local currentValue = tonumber(redis.call('get', KEYS[1])) " +
            "if currentValue and currentValue > 0 then " +
            "    redis.call('decr', KEYS[1]) " +
            "    return true " +
            "else " +
            "    return false " +
            "end";

        Object result = jedis.eval(luaScript, 1, key);
        return Boolean.TRUE.equals(result);
    }

    public static void main(String[] args) {
        RedisLuaDemo rd = new RedisLuaDemo("localhost", 6379);
        boolean result = rd.decrement("test");
        System.out.println(result);
    }
}

SpringBoot使用Lua案例

依赖导入

<!-- RedisTemplate 依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- redisClient 依赖-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.11.5</version>
</dependency>

将tpsLua.lua脚本放在resource目录下

脚本解析:获取key,key存在且值大于0则减1,返回true,否则返回fasle

local currentValue = tonumber(redis.call('get', KEYS[1]))
if currentValue and currentValue > 0 then
    redis.call('decr', KEYS[1])
    return true
else
    return false
end

代码案例

将脚本注入bean

/**
 * tps限制 lua脚本
 */
@Bean("tpsLuaScript")
public DefaultRedisScript<Boolean> script() {
    DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
    redisScript.setLocation(new ClassPathResource("tps.lua"));
    redisScript.setResultType(Boolean.class);
    return redisScript;
}

编写测试代码

@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class LuaTest {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private RedisScript<Boolean> tpsLuaScript;


    @Test
    public void testLua() throws InterruptedException {
        String flowKey = "test";
        for (int i = 0; i < 10; i++) {
            Thread.sleep(10);
            boolean execute1 = Optional.ofNullable(
                    (Boolean) redissonClient.getScript().eval(
                            RScript.Mode.READ_ONLY,
                            tpsLuaScript.getScriptAsString(),
                            RScript.ReturnType.BOOLEAN,
                            Collections.singletonList(flowKey),
                            Collections.emptyList())
            ).orElse(false);
            
            
            boolean execute2 = Optional.ofNullable(
                    redisTemplate.execute(
                            tpsLuaScript,
                            Collections.singletonList(flowKey),
                            Collections.EMPTY_LIST)
            ).orElse(false);
            
            log.info("{},{}", execute1, execute2);

        }

    }
}