脚本编写
可以通过调用 RedisTemplate
和 ReactiveRedisTemplate
的 execute
方法来运行脚本。两者都使用可配置的 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);
}
- Imperative
- Reactive
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
应为 Long
、Boolean
、List
或反序列化的值类型之一。如果脚本返回一个丢弃状态(特别是 OK
),它也可以是 null
。
在应用程序上下文中配置单个 DefaultRedisScript
实例是理想的做法,这样可以避免在每次脚本运行时重新计算脚本的 SHA1 值。
上面的 checkAndSet
方法随后会运行脚本。脚本可以在 SessionCallback 中作为事务或管道的一部分运行。有关更多信息,请参阅“Redis 事务”和“管道”。
Spring Data Redis 提供的脚本支持还允许您使用 Spring 任务和调度器抽象来安排 Redis 脚本定期运行。有关更多详细信息,请参阅 Spring Framework 文档。