diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index ee23268a4..93c4f7eea 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -24,7 +24,7 @@ This section briefly covers items that are new and noteworthy in the latest rele * <> support using Lettuce. * <> integration. * `@TypeAlias` Support for Redis repositories. -* Cluster-wide `SCAN` using Lettuce and `SCAN` execution on a selected node supported by both drivers. +* Cluster-wide `SCAN` using Lettuce and `SCAN` on a selected node supported by both drivers. * <> to send and receive a message stream. * `BITFIELD`, `BITPOS`, and `OBJECT` command support. * Align return types of `BoundZSetOperations` with `ZSetOperations`. diff --git a/src/main/asciidoc/reference/pipelining.adoc b/src/main/asciidoc/reference/pipelining.adoc index 8f5e61a37..53e26b043 100644 --- a/src/main/asciidoc/reference/pipelining.adoc +++ b/src/main/asciidoc/reference/pipelining.adoc @@ -3,7 +3,7 @@ Redis provides support for https://redis.io/topics/pipelining[pipelining], which involves sending multiple commands to the server without waiting for the replies and then reading the replies in a single step. Pipelining can improve performance when you need to send several commands in a row, such as adding many elements to the same List. -Spring Data Redis provides several `RedisTemplate` methods for executing commands in a pipeline. If you do not care about the results of the pipelined operations, you can use the standard `execute` method, passing `true` for the `pipeline` argument. The `executePipelined` methods run the provided `RedisCallback` or `SessionCallback` in a pipeline and return the results, as shown in the following example: +Spring Data Redis provides several `RedisTemplate` methods for running commands in a pipeline. If you do not care about the results of the pipelined operations, you can use the standard `execute` method, passing `true` for the `pipeline` argument. The `executePipelined` methods run the provided `RedisCallback` or `SessionCallback` in a pipeline and return the results, as shown in the following example: [source,java] ---- diff --git a/src/main/asciidoc/reference/query-by-example.adoc b/src/main/asciidoc/reference/query-by-example.adoc index 5ce394c17..360edf7f2 100644 --- a/src/main/asciidoc/reference/query-by-example.adoc +++ b/src/main/asciidoc/reference/query-by-example.adoc @@ -1,5 +1,5 @@ -[[query-by-example.execution]] -== Executing an Example +[[query-by-example.running]] +== Running an Example The following example uses Query by Example against a repository: @@ -26,7 +26,7 @@ In particular, only exact, case-sensitive, and non-null values are used to const Secondary indexes use set-based operations (Set intersection, Set union) to determine matching keys. Adding a property to the query that is not indexed returns no result, because no index exists. Query by Example support inspects indexing configuration to include only properties in the query that are covered by an index. This is to prevent accidental inclusion of non-indexed properties. -Case-insensitive queries and unsupported ``StringMatcher`` instances are rejected at runtime. +Case-insensitive queries and unsupported `StringMatcher` instances are rejected at runtime. The following list shows the supported Query by Example options: diff --git a/src/main/asciidoc/reference/reactive-messaging.adoc b/src/main/asciidoc/reference/reactive-messaging.adoc index 6b1e7e8af..fa7af9728 100644 --- a/src/main/asciidoc/reference/reactive-messaging.adoc +++ b/src/main/asciidoc/reference/reactive-messaging.adoc @@ -32,7 +32,7 @@ On the receiving side, one can subscribe to one or multiple channels either by n At the low-level, `ReactiveRedisConnection` offers `subscribe` and `pSubscribe` methods that map the Redis commands for subscribing by channel respectively by pattern. Note that multiple channels or patterns can be used as arguments. To change a subscription, simply query the channels and patterns of `ReactiveSubscription`. -NOTE: Reactive subscription commands in Spring Data Redis are non-blocking and may terminate without emitting an element. +NOTE: Reactive subscription commands in Spring Data Redis are non-blocking and may end without emitting an element. As mentioned above, once subscribed a connection starts waiting for messages. No other commands can be invoked on it except for adding new subscriptions or modifying/canceling the existing ones. Commands other than `subscribe`, `pSubscribe`, `unsubscribe`, or `pUnsubscribe` are illegal and will cause an exception. diff --git a/src/main/asciidoc/reference/reactive-redis.adoc b/src/main/asciidoc/reference/reactive-redis.adoc index 12a9b2b89..8bf0ecd12 100644 --- a/src/main/asciidoc/reference/reactive-redis.adoc +++ b/src/main/asciidoc/reference/reactive-redis.adoc @@ -168,7 +168,7 @@ include::{referenceDir}/reactive-messaging.adoc[leveloffset=+1] [[redis:reactive:scripting]] == Reactive Scripting -Executing Redis scripts via the reactive infrastructure can be done using the `ReactiveScriptExecutor` accessed best via `ReactiveRedisTemplate`. +You can run Redis scripts with the reactive infrastructure by using the `ReactiveScriptExecutor`, which is best accessed through `ReactiveRedisTemplate`. [source,java] ---- diff --git a/src/main/asciidoc/reference/redis-cluster.adoc b/src/main/asciidoc/reference/redis-cluster.adoc index cc7611355..8edf4d667 100644 --- a/src/main/asciidoc/reference/redis-cluster.adoc +++ b/src/main/asciidoc/reference/redis-cluster.adoc @@ -68,10 +68,10 @@ NOTE: The initial configuration points driver libraries to an initial set of clu [[cluster.working.with.cluster]] == Working With Redis Cluster Connection -As mentioned earlier, Redis Cluster behaves differently from single-node Redis or even a Sentinel-monitored master-replica environment. This is because the automatic sharding maps a key to one of 16384 slots, which are distributed across the nodes. Therefore, commands that involve more than one key must assert all keys map to the exact same slot to avoid cross-slot execution errors. +As mentioned earlier, Redis Cluster behaves differently from single-node Redis or even a Sentinel-monitored master-replica environment. This is because the automatic sharding maps a key to one of 16384 slots, which are distributed across the nodes. Therefore, commands that involve more than one key must assert all keys map to the exact same slot to avoid cross-slot errors. A single cluster node serves only a dedicated set of keys. Commands issued against one particular server return results only for those keys served by that server. As a simple example, consider the `KEYS` command. When issued to a server in a cluster environment, it returns only the keys served by the node the request is sent to and not necessarily all keys within the cluster. So, to get all keys in a cluster environment, you must read the keys from all the known master nodes. -While redirects for specific keys to the corresponding slot-serving node are handled by the driver libraries, higher-level functions, such as collecting information across nodes or sending commands to all nodes in the cluster, are covered by `RedisClusterConnection`. Picking up the keys example from earlier, this means that the `keys(pattern)` method picks up every master node in the cluster and simultaneously executes the `KEYS` command on every master node while picking up the results and returning the cumulated set of keys. To just request the keys of a single node `RedisClusterConnection` provides overloads for those methods (for example, `keys(node, pattern)`). +While redirects for specific keys to the corresponding slot-serving node are handled by the driver libraries, higher-level functions, such as collecting information across nodes or sending commands to all nodes in the cluster, are covered by `RedisClusterConnection`. Picking up the keys example from earlier, this means that the `keys(pattern)` method picks up every master node in the cluster and simultaneously runs the `KEYS` command on every master node while picking up the results and returning the cumulated set of keys. To just request the keys of a single node `RedisClusterConnection` provides overloads for those methods (for example, `keys(node, pattern)`). A `RedisClusterNode` can be obtained from `RedisClusterConnection.clusterGetNodes` or it can be constructed by using either the host and the port or the node Id. @@ -116,7 +116,7 @@ connection.keys(NODE_7382, "*"); < <11> Request routed to node at 7382 -> [thing2] ==== -When all keys map to the same slot, the native driver library automatically serves cross-slot requests, such as `MGET`. However, once this is not the case, `RedisClusterConnection` executes multiple parallel `GET` commands against the slot-serving nodes and again returns an accumulated result. This is less performant than the single-slot execution and, therefore, should be used with care. If in doubt, consider pinning keys to the same slot by providing a prefix in curly brackets, such as `{my-prefix}.thing1` and `{my-prefix}.thing2`, which will both map to the same slot number. The following example shows cross-slot request handling: +When all keys map to the same slot, the native driver library automatically serves cross-slot requests, such as `MGET`. However, once this is not the case, `RedisClusterConnection` runs multiple parallel `GET` commands against the slot-serving nodes and again returns an accumulated result. This is less performant than the single-slot approach and, therefore, should be used with care. If in doubt, consider pinning keys to the same slot by providing a prefix in curly brackets, such as `{my-prefix}.thing1` and `{my-prefix}.thing2`, which will both map to the same slot number. The following example shows cross-slot request handling: .Sample of Cross-Slot Request Handling ==== diff --git a/src/main/asciidoc/reference/redis-repositories.adoc b/src/main/asciidoc/reference/redis-repositories.adoc index ff53d4250..9729f44ae 100644 --- a/src/main/asciidoc/reference/redis-repositories.adoc +++ b/src/main/asciidoc/reference/redis-repositories.adoc @@ -579,7 +579,7 @@ NOTE: Annotating a property explicitly with `@TimeToLive` reads back the actual The repository implementation ensures subscription to https://redis.io/topics/notifications[Redis keyspace notifications] via `RedisMessageListenerContainer`. -When the expiration is set to a positive value, the corresponding `EXPIRE` command is executed. In addition to persisting the original, a phantom copy is persisted in Redis and set to expire five minutes after the original one. This is done to enable the Repository support to publish `RedisKeyExpiredEvent`, holding the expired value in Spring's `ApplicationEventPublisher` whenever a key expires, even though the original values have already been removed. Expiry events are received on all connected applications that use Spring Data Redis repositories. +When the expiration is set to a positive value, the corresponding `EXPIRE` command is run. In addition to persisting the original, a phantom copy is persisted in Redis and set to expire five minutes after the original one. This is done to enable the Repository support to publish `RedisKeyExpiredEvent`, holding the expired value in Spring's `ApplicationEventPublisher` whenever a key expires, even though the original values have already been removed. Expiry events are received on all connected applications that use Spring Data Redis repositories. By default, the key expiry listener is disabled when initializing the application. The startup mode can be adjusted in `@EnableRedisRepositories` or `RedisKeyValueAdapter` to start the listener with the application or upon the first insert of an entity with a TTL. See https://docs.spring.io/spring-data/redis/docs/{revnumber}/api/org/springframework/data/redis/core/RedisKeyValueAdapter.EnableKeyspaceEvents.html[`EnableKeyspaceEvents`] for possible values. @@ -671,7 +671,7 @@ NOTE: Please make sure properties used in finder methods are set up for indexing NOTE: Query methods for Redis repositories support only queries for entities and collections of entities with paging. -Using derived query methods might not always be sufficient to model the queries to execute. `RedisCallback` offers more control over the actual matching of index structures or even custom indexes. To do so, provide a `RedisCallback` that returns a single or `Iterable` set of `id` values, as shown in the following example: +Using derived query methods might not always be sufficient to model the queries to run. `RedisCallback` offers more control over the actual matching of index structures or even custom indexes. To do so, provide a `RedisCallback` that returns a single or `Iterable` set of `id` values, as shown in the following example: .Sample finder using RedisCallback ==== diff --git a/src/main/asciidoc/reference/redis-scripting.adoc b/src/main/asciidoc/reference/redis-scripting.adoc index 3c4fdb97f..3a3adda7e 100644 --- a/src/main/asciidoc/reference/redis-scripting.adoc +++ b/src/main/asciidoc/reference/redis-scripting.adoc @@ -1,7 +1,7 @@ [[scripting]] = Redis Scripting -Redis versions 2.6 and higher provide support for execution of Lua scripts through the https://redis.io/commands/eval[eval] and https://redis.io/commands/evalsha[evalsha] commands. Spring Data Redis provides a high-level abstraction for script execution that handles serialization and automatically uses the Redis script cache. +Redis versions 2.6 and higher provide support for running Lua scripts through the https://redis.io/commands/eval[eval] and https://redis.io/commands/evalsha[evalsha] commands. Spring Data Redis provides a high-level abstraction for running scripts 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. @@ -14,7 +14,7 @@ The following example runs a common "`check-and-set`" scenario by using a Lua sc @Bean public RedisScript script() { - ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("META-INF/scripts/checkandset.lua"); + ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("META-INF/scripts/checkandset.lua")); return RedisScript.of(scriptSource, Boolean.class); } ---- @@ -45,8 +45,8 @@ 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`). -TIP: 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. +TIP: 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 run. The `checkAndSet` method above then runs the scripts. Scripts can be run within a `SessionCallback` as part of a transaction or pipeline. See "`<>`" and "`<>`" 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 https://projects.spring.io/spring-framework/[Spring Framework] documentation for more details. +The scripting support provided by Spring Data Redis also lets you schedule Redis scripts for periodic running by using the Spring Task and Scheduler abstractions. See the https://projects.spring.io/spring-framework/[Spring Framework] documentation for more details. diff --git a/src/main/asciidoc/reference/redis-transactions.adoc b/src/main/asciidoc/reference/redis-transactions.adoc index 203e8ed1a..5f3b7b582 100644 --- a/src/main/asciidoc/reference/redis-transactions.adoc +++ b/src/main/asciidoc/reference/redis-transactions.adoc @@ -1,7 +1,7 @@ [[tx]] = Redis Transactions -Redis provides support for https://redis.io/topics/transactions[transactions] through the `multi`, `exec`, and `discard` commands. These operations are available on `RedisTemplate`. However, `RedisTemplate` is not guaranteed to execute all operations in the transaction with the same connection. +Redis provides support for https://redis.io/topics/transactions[transactions] through the `multi`, `exec`, and `discard` commands. These operations are available on `RedisTemplate`. However, `RedisTemplate` is not guaranteed to run all the operations in the transaction with the same connection. Spring Data Redis provides the `SessionCallback` interface for use when multiple operations need to be performed with the same `connection`, such as when using Redis transactions. The following example uses the `multi` method: @@ -77,7 +77,7 @@ The following examples each demonstrate a usage constraint: // must be performed on thread-bound connection template.opsForValue().set("thing1", "thing2"); -// read operation must be executed on a free (not transaction-aware) connection +// read operation must be run on a free (not transaction-aware) connection template.keys("*"); // returns null as values set within a transaction are not visible diff --git a/src/main/asciidoc/reference/redis.adoc b/src/main/asciidoc/reference/redis.adoc index 2823e4206..5a76d2715 100644 --- a/src/main/asciidoc/reference/redis.adoc +++ b/src/main/asciidoc/reference/redis.adoc @@ -504,7 +504,7 @@ Do note that the storage format is not limited only to values. It can be used fo [WARNING] ==== -By default, `RedisCache` and `RedisTemplate` are configured to use Java native serialization. Java native serialization is known for allowing remote code execution caused by payloads that exploit vulnerable libraries and classes injecting unverified bytecode. Manipulated input could lead to unwanted code execution in the application during the deserialization step. As a consequence, do not use serialization in untrusted environments. In general, we strongly recommend any other message format (such as JSON) instead. +By default, `RedisCache` and `RedisTemplate` are configured to use Java native serialization. Java native serialization is known for allowing the running of remote code caused by payloads that exploit vulnerable libraries and classes injecting unverified bytecode. Manipulated input could lead to unwanted code being run in the application during the deserialization step. As a consequence, do not use serialization in untrusted environments. In general, we strongly recommend any other message format (such as JSON) instead. If you are concerned about security vulnerabilities due to Java serialization, consider the general-purpose serialization filter mechanism at the core JVM level, originally developed for JDK 9 but backported to JDK 8, 7, and 6: