Skip to content

Lua

为什么要用

  1. 原子性操作
    Redis 的 Lua 脚本在执行过程中是原子的,这意味着所有命令在脚本中要么全部执行,要么全部不执行。这样可以确保在执行过程中不会有其他客户端对 Redis 状态的干扰,从而保证数据的一致性和完整性。
  2. 减少网络延迟
    通过 Lua 脚本,客户端可以将多个 Redis 命令封装在一个脚本中发送给 Redis 服务器执行。这样可以减少多次网络通信带来的延迟,从而提高操作的效率。
  3. 复杂操作
    Lua 脚本可以处理复杂的逻辑,允许你在 Redis 中执行一些比较复杂的操作,比如条件判断、循环等。这样可以在服务器端完成一些原本需要在客户端完成的复杂逻辑处理。
  4. 代码复用
    Lua 脚本可以在 Redis 中注册并反复调用,实现代码复用。这在需要频繁执行的复杂操作中非常有用。

简单示例

lua
-- increment.lua
local key = KEYS[1]
local increment = tonumber(ARGV[1])
local current = tonumber(redis.call('GET', key) or 0)
redis.call('SET', key, current + increment)
return current + increment
lua
-- compare_and_set.lua
local key = KEYS[1]
local new_value = tonumber(ARGV[1])
local current_value = tonumber(redis.call('GET', key) or 0)
if current_value < new_value then
    redis.call('SET', key, new_value)
    return new_value
else
    return current_value
end
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Collections;

@Service
public class RedisService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public Integer increment(String key, int increment) {
        String script = "local key = KEYS[1]\n" +
                        "local increment = tonumber(ARGV[1])\n" +
                        "local current = tonumber(redis.call('GET', key) or 0)\n" +
                        "redis.call('SET', key, current + increment)\n" +
                        "return current + increment";
        // 定义 RedisScript
        DefaultRedisScript<Integer> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(script);
        redisScript.setResultType(Integer.class);
        // 执行 Lua 脚本
        return stringRedisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(increment));
    }
}