DATAREDIS-619 - Polishing.

Add dedicated section on executing lua scripts via the reactive infrastructure, rephrase some other parts adapt non-Javadoc comments to code style.

Original Pull Request: #280
This commit is contained in:
Christoph Strobl
2017-10-12 14:33:25 +02:00
parent 17676dc681
commit e53335f0ae
2 changed files with 90 additions and 44 deletions

View File

@@ -7,7 +7,7 @@ This section covers reactive Redis support and how to get started. You will find
[[redis:reactive:requirements]]
== Redis Requirements
Spring Redis requires Redis 2.6 or above and Java SE 8.0 or above. In terms of language bindings (or connectors), Spring Data Redis integrates with http://github.com/lettuce-io/lettuce-core[Lettuce] as the only reactive Java connector. Spring Data Redis uses https://projectreactor.io/[Project Reactor] as reactive composition library.
Spring Data Redis requires Redis 2.6 or above and Java SE 8.0 or above. In terms of language bindings (or connectors), Spring Data Redis currently integrates with http://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 using a reactive driver
@@ -17,13 +17,13 @@ One of the first tasks when using Redis and Spring is to connect to the store th
[[redis:reactive:connectors:operation-modes]]
=== Redis Operation Modes
Redis can be run as Standalone server, with <<redis:sentinel,Redis Sentinel>> or in <<cluster,Redis Cluster>> mode.
Redis can be run as standalone server, with <<redis:sentinel,Redis Sentinel>> or in <<cluster,Redis Cluster>> mode.
http://github.com/lettuce-io/lettuce-core[Lettuce] supports all above mentioned connection types.
[[redis:reactive:connectors:connection]]
=== ReactiveRedisConnection and ReactiveRedisConnectionFactory
`ReactiveRedisConnection` provides the building block for Redis communication as it handles the communication with the Redis back-end. It also automatically translates the underlying connecting library exceptions to Spring's consistent DAO exception http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#dao-exceptions[hierarchy] so one can switch the connectors without any code changes as the operation semantics remain the same.
`ReactiveRedisConnection` provides the building block for 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 http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#dao-exceptions[hierarchy] so one can switch the connectors without any code changes as the operation semantics remain the same.
Active ``ReactiveRedisConnection``s are created through `ReactiveRedisConnectionFactory`. In addition, the factories act as ``PersistenceExceptionTranslator``s, meaning once declared, they allow one to do transparent exception translation. For example, exception translation through the use of the `@Repository` annotation and AOP. For more information see the dedicated http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#orm-exception-translation[section] in Spring Framework documentation.
@@ -34,45 +34,43 @@ The easiest way to work with a `ReactiveRedisConnectionFactory` is to configure
[[redis:reactive:connectors:lettuce]]
=== Configuring Lettuce connector
https://github.com/lettuce-io/lettuce-core[Lettuce] is a http://netty.io/[netty]-based open-source connector supported by Spring Data Redis through the `org.springframework.data.redis.connection.lettuce` package.
https://github.com/lettuce-io/lettuce-core[Lettuce] is supported by Spring Data Redis through the `org.springframework.data.redis.connection.lettuce` package.
Its configuration is probably easy to guess:
Setting up `ReactiveRedisConnectionFactory` for Lettuce can be done as follows:
[source,java]
----
@Bean
public ReactiveRedisConnectionFactory lettuceConnectionFactory() {
public ReactiveRedisConnectionFactory connectionFactory() {
return new LettuceConnectionFactory("localhost", 6379);
}
----
A more sophisticated configuration could look like:
A more sophisticated configuration, including SSL and timeouts, using `LettuceClientConfigurationBuilder` might look like below:
[source,java]
----
@Bean
public ReactiveRedisConnectionFactory lettuceConnectionFactory() {
RedisStandaloneConfiguration standalone = new RedisStandaloneConfiguration("localhost", 6379);
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.useSsl().and()
.commandTimeout(Duration.ofSeconds(2))
.shutdownTimeout(Duration.ZERO)
.build();
return new LettuceConnectionFactory(standalone, clientConfig);
return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379), clientConfig);
}
----
There are also a few Lettuce-specific connection parameters that can be tweaked. See `LettuceClientConfiguration` for more details.
For more detailed client configuration tweaks have a look at `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` - the template is in fact the central class of the Redis module due to its rich feature set. 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 the user from dealing with such details.
Moreover, the template provides operations views (following the grouping from Redis command http://redis.io/commands[reference]) that offer rich, generified interfaces for working against a certain type as described below:
Moreover, the template provides operation views (following the grouping from Redis command http://redis.io/commands[reference]) that offer rich, generified interfaces for working against a certain type as described below:
.Operational views
[width="80%",cols="<1,<2",options="header"]
@@ -106,7 +104,7 @@ Moreover, the template provides operations views (following the grouping from Re
Once configured, the template is thread-safe and can be reused across multiple instances.
Out of the box, `ReactiveRedisTemplate` uses a Java-based serializer for most of its operations. This means that any object written or read by the template will be serialized/deserialized through Java throug `RedisElementWriter` respective `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.
Out of the box, `ReactiveRedisTemplate` uses a Java-based serializer for most of its operations. This means that any object written or read by the template will be serialized/deserialized through `RedisElementWriter` respective `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.
[source,java]
----
@@ -124,15 +122,36 @@ class RedisConfiguration {
----
public class Example {
// inject the actual template
@Autowired
private ReactiveRedisTemplate<String, String> template;
public Mono<Long> addLink(String userId, URL url) {
return template.opsForList().leftPush(userId, url.toExternalForm());
}
}
----
== Reactive Scripting
Executing Redis scripts via the reactive infrastructure can be done using the `ReactiveScriptExecutor` accessed best via `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);
}
}
----
Please refer to the <<scripting,scripting section>> for more details on scripting commands.

View File

@@ -102,7 +102,6 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return connectionFactory;
}
// -------------------------------------------------------------------------
// Execution methods
// -------------------------------------------------------------------------
@@ -198,7 +197,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
// Methods dealing with Redis keys
// -------------------------------------------------------------------------
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#hasKey(java.lang.Object)
*/
@Override
@@ -209,7 +209,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> connection.keyCommands().exists(rawKey(key)));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#type(java.lang.Object)
*/
@Override
@@ -220,7 +221,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> connection.keyCommands().type(rawKey(key)));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#keys(java.lang.Object)
*/
@Override
@@ -233,7 +235,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
.map(this::readKey);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#randomKey()
*/
@Override
@@ -241,7 +244,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> connection.keyCommands().randomKey()).map(this::readKey);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#rename(java.lang.Object, java.lang.Object)
*/
@Override
@@ -253,7 +257,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> connection.keyCommands().rename(rawKey(oldKey), rawKey(newKey)));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#renameIfAbsent(java.lang.Object, java.lang.Object)
*/
@Override
@@ -265,7 +270,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> connection.keyCommands().renameNX(rawKey(oldKey), rawKey(newKey)));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#delete(java.lang.Object[])
*/
@Override
@@ -284,7 +290,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> listOfKeys.flatMap(rawKeys -> connection.keyCommands().mDel(rawKeys)));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#delete(org.reactivestreams.Publisher)
*/
@Override
@@ -297,7 +304,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
.map(CommandResponse::getOutput));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#expire(java.lang.Object, java.time.Duration)
*/
@Override
@@ -314,7 +322,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> connection.keyCommands().pExpire(rawKey(key), timeout));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#expireAt(java.lang.Object, java.time.Instant)
*/
@Override
@@ -331,7 +340,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> connection.keyCommands().pExpireAt(rawKey(key), expireAt));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#persist(java.lang.Object)
*/
@Override
@@ -342,7 +352,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return createMono(connection -> connection.keyCommands().persist(rawKey(key)));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#getExpire(java.lang.Object)
*/
@Override
@@ -364,7 +375,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
}));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#move(java.lang.Object, int)
*/
@Override
@@ -435,7 +447,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
new CloseSuppressingInvocationHandler(reactiveRedisConnection));
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForGeo()
*/
@Override
@@ -443,7 +456,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return opsForGeo(serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForGeo(org.springframework.data.redis.serializer.RedisSerializationContext)
*/
@Override
@@ -451,7 +465,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return new DefaultReactiveGeoOperations<>(this, serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHash()
*/
@Override
@@ -459,7 +474,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return opsForHash(serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHash(org.springframework.data.redis.serializer.RedisSerializationContext)
*/
@Override
@@ -468,7 +484,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return new DefaultReactiveHashOperations<>(this, serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHyperLogLog()
*/
@Override
@@ -476,7 +493,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return opsForHyperLogLog(serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHyperLogLog(org.springframework.data.redis.serializer.RedisSerializationContext)
*/
@Override
@@ -485,7 +503,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return new DefaultReactiveHyperLogLogOperations<>(this, serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForList()
*/
@Override
@@ -493,7 +512,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return opsForList(serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForList(org.springframework.data.redis.serializer.RedisSerializationContext)
*/
@Override
@@ -501,7 +521,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return new DefaultReactiveListOperations<>(this, serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForSet()
*/
@Override
@@ -509,7 +530,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return opsForSet(serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForSet(org.springframework.data.redis.serializer.RedisSerializationContext)
*/
@Override
@@ -517,7 +539,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return new DefaultReactiveSetOperations<>(this, serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForValue()
*/
@Override
@@ -525,7 +548,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return opsForValue(serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForValue(org.springframework.data.redis.serializer.RedisSerializationContext)
*/
@Override
@@ -533,7 +557,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return new DefaultReactiveValueOperations<>(this, serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForZSet()
*/
@Override
@@ -541,7 +566,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return opsForZSet(serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForZSet(org.springframework.data.redis.serializer.RedisSerializationContext)
*/
@Override
@@ -549,7 +575,8 @@ public class ReactiveRedisTemplate<K, V> implements ReactiveRedisOperations<K, V
return new DefaultReactiveZSetOperations<>(this, serializationContext);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveRedisOperations#serialization()
*/
@Override