指令碼
Redis 2.6 及更高版本透過 eval 和 evalsha 命令支援執行 Lua 指令碼。Spring Data Redis 提供了一種高階抽象來執行指令碼,它處理序列化並自動使用 Redis 指令碼快取。
指令碼可以透過呼叫 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);
}
-
命令式
-
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
上述程式碼配置了一個 RedisScript,指向名為 checkandset.lua 的檔案,該檔案預期返回一個布林值。指令碼的 resultType 應該是 Long、Boolean、List 之一,或一個反序列化的值型別。如果指令碼返回一個一次性狀態(具體來說是 OK),它也可以是 null。
理想情況下,在應用程式上下文中配置一個 DefaultRedisScript 例項,以避免在每次指令碼執行時重新計算指令碼的 SHA1。 |
上述 checkAndSet 方法隨後執行指令碼。指令碼可以在 SessionCallback 中作為事務或管道的一部分執行。有關更多資訊,請參閱“Redis 事務”和“管道”。
Spring Data Redis 提供的指令碼支援還允許您使用 Spring Task 和 Scheduler 抽象來排程 Redis 指令碼以進行定期執行。有關更多詳細資訊,請參閱 Spring Framework 文件。