[[redis:reactive]]
= Reactive Redis support
:referenceDir: .

This section covers reactive Redis support and how to get started. Reactive Redis support naturally has certain overlaps with <<redis,imperative Redis support>>.

[[redis:reactive:requirements]]
== Redis Requirements

Spring Data Redis currently integrates with https://github.com/lettuce-io/lettuce-core[Lettuce] as the only reactive Java connector. https://projectreactor.io/[Project Reactor] is used as reactive composition library.

[[redis:reactive:connectors]]
== Connecting to Redis by Using a Reactive Driver

One of the first tasks when using Redis and Spring is to connect to the store through the IoC container. To do that, a Java connector (or binding) is required. No matter the library you choose, you must use the `org.springframework.data.redis.connection` package and its `ReactiveRedisConnection` and `ReactiveRedisConnectionFactory` interfaces to work with and retrieve active `connections` to Redis.

[[redis:reactive:connectors:operation-modes]]
=== Redis Operation Modes

Redis can be run as a standalone server, with <<redis:sentinel,Redis Sentinel>>, or in <<cluster,Redis Cluster>> mode.
https://github.com/lettuce-io/lettuce-core[Lettuce] supports all of the previously mentioned connection types.

[[redis:reactive:connectors:connection]]
=== `ReactiveRedisConnection` and `ReactiveRedisConnectionFactory`

`ReactiveRedisConnection` is the core of Redis communication, as it handles the communication with the Redis back-end. It also automatically translates the underlying driver exceptions to Spring's consistent DAO exception https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#dao-exceptions[hierarchy], so you can switch the connectors without any code changes, as the operation semantics remain the same.

`ReactiveRedisConnectionFactory` creates active `ReactiveRedisConnection` instances. In addition, the factories act as `PersistenceExceptionTranslator` instances, meaning that, once declared, they let you do transparent exception translation -- for example, exception translation through the use of the `@Repository` annotation and AOP. For more information, see the dedicated https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#orm-exception-translation[section] in the Spring Framework documentation.

NOTE: Depending on the underlying configuration, the factory can return a new connection or an existing connection (in case a pool or shared native connection is used).

TIP: The easiest way to work with a `ReactiveRedisConnectionFactory` is to configure the appropriate connector through the IoC container and inject it into the using class.

[[redis:reactive:connectors:lettuce]]
=== Configuring a Lettuce Connector

https://github.com/lettuce-io/lettuce-core[Lettuce] is supported by Spring Data Redis through the `org.springframework.data.redis.connection.lettuce` package.

You can set up `ReactiveRedisConnectionFactory` for Lettuce as follows:

[source,java]
----
@Bean
public ReactiveRedisConnectionFactory connectionFactory() {
  return new LettuceConnectionFactory("localhost", 6379);
}
----

The following example shows a more sophisticated configuration, including SSL and timeouts, that uses `LettuceClientConfigurationBuilder`:

[source,java]
----
@Bean
public ReactiveRedisConnectionFactory lettuceConnectionFactory() {

  LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
    .useSsl().and()
    .commandTimeout(Duration.ofSeconds(2))
    .shutdownTimeout(Duration.ZERO)
    .build();

  return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379), clientConfig);
}
----

For more detailed client configuration tweaks, see https://docs.spring.io/spring-data/redis/docs/{revnumber}/api/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.html[`LettuceClientConfiguration`].

[[redis:reactive:template]]
== Working with Objects through ReactiveRedisTemplate

Most users are likely to use `ReactiveRedisTemplate` and its corresponding package, `org.springframework.data.redis.core`. Due to its rich feature set, the template is, in fact, the central class of the Redis module. The template offers a high-level abstraction for Redis interactions. While `ReactiveRedisConnection` offers low-level methods that accept and return binary values (`ByteBuffer`), the template takes care of serialization and connection management, freeing you from dealing with such details.

Moreover, the template provides operation views (following the grouping from Redis command https://redis.io/commands[reference]) that offer rich, generified interfaces for working against a certain type as described in the following table:

.Operational views
[width="80%",cols="<1,<2",options="header"]
|====
|Interface
|Description

2+^|_Key Type Operations_

|ReactiveGeoOperations
|Redis geospatial operations such as `GEOADD`, `GEORADIUS`, and others)

|ReactiveHashOperations
|Redis hash operations

|ReactiveHyperLogLogOperations
|Redis HyperLogLog operations such as (`PFADD`, `PFCOUNT`, and others)

|ReactiveListOperations
|Redis list operations

|ReactiveSetOperations
|Redis set operations

|ReactiveValueOperations
|Redis string (or value) operations

|ReactiveZSetOperations
|Redis zset (or sorted set) operations
|====

Once configured, the template is thread-safe and can be reused across multiple instances.

`ReactiveRedisTemplate` uses a Java-based serializer for most of its operations. This means that any object written or read by the template is serialized or deserialized through `RedisElementWriter` or `RedisElementReader`. The serialization context is passed to the template upon construction, and the Redis module offers several implementations available in the `org.springframework.data.redis.serializer` package. See <<redis:serializer>> for more information.

The following example shows a `ReactiveRedisTemplate` being used to return a `Mono`:

[source,java]
----
@Configuration
class RedisConfiguration {

  @Bean
  ReactiveRedisTemplate<String, String> reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) {
    return new ReactiveRedisTemplate<>(factory, RedisSerializationContext.string());
  }
}
----

[source,java]
----
public class Example {

  @Autowired
  private ReactiveRedisTemplate<String, String> template;

  public Mono<Long> addLink(String userId, URL url) {
    return template.opsForList().leftPush(userId, url.toExternalForm());
  }
}
----

[[redis:reactive:string]]
== String-focused Convenience Classes

Since it is quite common for keys and values stored in Redis to be a `java.lang.String`, the Redis module provides a String-based extension to `ReactiveRedisTemplate`: `ReactiveStringRedisTemplate`. It is a convenient one-stop solution for intensive `String` operations. In addition to being bound to `String` keys, the template uses the String-based `RedisSerializationContext`, which means the stored keys and values are human readable (assuming the same encoding is used in both Redis and your code). The following example shows `ReactiveStringRedisTemplate` in use:

[source,java]
----
@Configuration
class RedisConfiguration {

  @Bean
  ReactiveStringRedisTemplate reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) {
    return new ReactiveStringRedisTemplate<>(factory);
  }
}
----

[source,java]
----
public class Example {

  @Autowired
  private ReactiveStringRedisTemplate redisTemplate;

  public Mono<Long> addLink(String userId, URL url) {
    return redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
  }
}
----

include::{referenceDir}/reactive-messaging.adoc[leveloffset=+1]

[[redis:reactive:scripting]]
== Reactive Scripting

You can run Redis scripts with the reactive infrastructure by using the `ReactiveScriptExecutor`, which is best accessed through `ReactiveRedisTemplate`.

[source,java]
----
public class Example {

  @Autowired
  private ReactiveRedisTemplate<String, String> template;

  public Flux<Long> theAnswerToLife() {

    DefaultRedisScript<Long> script = new DefaultRedisScript<>();
    script.setLocation(new ClassPathResource("META-INF/scripts/42.lua"));
    script.setResultType(Long.class);

    return reactiveTemplate.execute(script);
  }
}
----

See to the <<scripting,scripting section>> for more details on scripting commands.
