脚本

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

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

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

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

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