指令碼
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);
}
-
命令式
-
響應式
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 文件。