Redis Scripting

Redis versions 2.6 and higher provide support for execution of Lua scripts through the eval and evalsha commands. Spring Data Redis provides a high-level abstraction for script execution that handles serialization and automatically uses the Redis script cache.

Scripts can be run by calling the execute methods of RedisTemplate and ReactiveRedisTemplate. Both use a configurable ScriptExecutor (or ReactiveScriptExecutor) to run the provided script. By default, the ScriptExecutor (or ReactiveScriptExecutor) takes care of serializing the provided keys and arguments and deserializing the script result. This is done through the key and value serializers of the template. There is an additional overload that lets you pass custom serializers for the script arguments and the result.

The default ScriptExecutor optimizes performance by retrieving the SHA1 of the script and attempting first to run evalsha, falling back to eval if the script is not yet present in the Redis script cache.

The following example runs a common “check-and-set” scenario by using a Lua script. This is an ideal use case for a Redis script, as it requires that running a set of commands atomically, and the behavior of one command is influenced by the result of another.

@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
  RedisScript<Boolean> script;

  public boolean checkAndSet(String expectedValue, String newValue) {
    return redisTemplate.execute(script, singletonList("key"), asList(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

The preceding code configures a RedisScript pointing to a file called checkandset.lua, which is expected to return a boolean value. The script resultType should be one of Long, Boolean, List, or a deserialized value type. It can also be null if the script returns a throw-away status (specifically, OK).

It is ideal to configure a single instance of DefaultRedisScript in your application context to avoid re-calculation of the script’s SHA1 on every script execution.

The checkAndSet method above then runs the scripts. Scripts can be run within a SessionCallback as part of a transaction or pipeline. See “tx” and “pipeline” for more information.

The scripting support provided by Spring Data Redis also lets you schedule Redis scripts for periodic execution by using the Spring Task and Scheduler abstractions. See the Spring Framework documentation for more details.