脚本

Redis 2.6 及更高版本支持通过 evalevalsha 命令运行 Lua 脚本。Spring Data Redis 提供了一个高级抽象来运行脚本,该抽象处理序列化并自动使用 Redis 脚本缓存。

可以通过调用 RedisTemplateReactiveRedisTemplateexecute 方法来运行脚本。两者都使用可配置的 ScriptExecutor(或 ReactiveScriptExecutor)来运行提供的脚本。默认情况下,ScriptExecutor(或 ReactiveScriptExecutor)负责序列化提供的键和参数以及反序列化脚本结果。这是通过模板的键和值序列化程序完成的。还有一个额外的重载,允许您为脚本参数和结果传递自定义序列化程序。

默认的 ScriptExecutor 通过检索脚本的 SHA1 并首先尝试运行 evalsha 来优化性能,如果脚本尚未存在于 Redis 脚本缓存中,则回退到 eval

以下示例使用 Lua 脚本运行常见的“检查和设置”场景。这是 Redis 脚本的理想用例,因为它需要以原子方式运行一组命令,并且一个命令的行为受另一个命令的结果影响。

@Bean
public RedisScript<Boolean> script() {

  ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("META-INF/scripts/checkandset.lua"));
  return RedisScript.of(scriptSource, Boolean.class);
}
  • 命令式

  • 响应式

public class Example {

  @Autowired
  RedisOperations<String, String> redisOperations;

  @Autowired
  RedisScript<Boolean> script;

  public boolean checkAndSet(String expectedValue, String newValue) {
    return redisOperations.execute(script, List.of("key"), expectedValue, newValue);
  }
}
public class Example {

  @Autowired
  ReactiveRedisOperations<String, String> redisOperations;

  @Autowired
  RedisScript<Boolean> script;

  public Flux<Boolean> checkAndSet(String expectedValue, String newValue) {
    return redisOperations.execute(script, List.of("key"), expectedValue, newValue);
  }
}
-- checkandset.lua
local current = redis.call('GET', KEYS[1])
if current == ARGV[1]
  then redis.call('SET', KEYS[1], ARGV[2])
  return true
end
return false

前面的代码配置了一个指向名为 checkandset.lua 的文件的 RedisScript,该文件预计将返回一个布尔值。脚本 resultType 应为 LongBooleanList 或反序列化的值类型之一。如果脚本返回一个一次性状态(特别是 OK),它也可以是 null

理想情况下,在您的应用程序上下文中配置 DefaultRedisScript 的单个实例,以避免在每次脚本运行时重新计算脚本的 SHA1。

上面的 checkAndSet 方法然后运行脚本。脚本可以在 SessionCallback 中作为事务或管道的一部分运行。有关更多信息,请参阅“Redis 事务”和“管道”。

Spring Data Redis 提供的脚本支持还允许您使用 Spring 任务和调度程序抽象来安排 Redis 脚本定期运行。有关更多详细信息,请参阅 Spring Framework 文档。