Skip to content

Commit 7d306ed

Browse files
committed
Polishing.
Tweak wording around thread-safety. Include notices in connection factories. Reformat asciidoc. See #2653 Original pull request: #2667
1 parent 48b765d commit 7d306ed

File tree

9 files changed

+41
-23
lines changed

9 files changed

+41
-23
lines changed

Diff for: src/main/asciidoc/reference/redis.adoc

+9-3
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,15 @@ NOTE: For the corner cases where the native library API is required, `RedisConne
8080

8181
Active `RedisConnection` objects are created through `RedisConnectionFactory`. In addition, the factory acts as `PersistenceExceptionTranslator` objects, meaning that, once declared, they let you do transparent exception translation. For example, you can do exception translation through the use of the `@Repository` annotation and AOP. For more information, see the dedicated {spring-framework-reference}/data-access.html#orm-exception-translation[section] in the Spring Framework documentation.
8282

83-
WARNING: `RedisConnection` classes, such as `JedisConnection` and `LettuceConnection`, are **not** Thread-safe. While the underlying native connection, such as Lettuce's `StatefulRedisConnection`, may be Thread-safe, Spring Data Redis's `LettuceConnection` class itself is not Thread-safe. Therefore, you should **not** share instances of a `RedisConnection` across multiple Threads. This is especially true for transactional, or blocking Redis operations and commands, such as `BLPOP`. In transactional and pipelining operations, for instance, `RedisConnection` holds onto unguarded mutable state to complete the operation correctly, thereby making it unsafe to use with multiple Threads. This is by design.
84-
85-
TIP: If you need to share (stateful) Redis resources, like connections, across multiple Threads, for performance reasons or otherwise, then you should acquire the native connection and use the Redis client library (driver) API directly. Alternatively, you can use the `RedisTemplate`, which acquires and manages connections for operations (and Redis commands) in a Thread-safe manner. See <<redis:template,documentation>> on `RedisTemplate` for more details.
83+
NOTE: `RedisConnection` classes are **not** Thread-safe.
84+
While the underlying native connection, such as Lettuce's `StatefulRedisConnection`, may be Thread-safe, Spring Data Redis's `LettuceConnection` class itself is not.
85+
Therefore, you should **not** share instances of a `RedisConnection` across multiple Threads.
86+
This is especially true for transactional, or blocking Redis operations and commands, such as `BLPOP`.
87+
In transactional and pipelining operations, for instance, `RedisConnection` holds onto unguarded mutable state to complete the operation correctly, thereby making it unsafe to use with multiple Threads.
88+
This is by design.
89+
90+
TIP: If you need to share (stateful) Redis resources, like connections, across multiple Threads, for performance reasons or otherwise, then you should acquire the native connection and use the Redis client library (driver) API directly.
91+
Alternatively, you can use the `RedisTemplate`, which acquires and manages connections for operations (and Redis commands) in a Thread-safe manner. See <<redis:template,documentation>> on `RedisTemplate` for more details.
8692

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

Diff for: src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
* {@link RedisClusterNode} can be obtained from {@link #clusterGetNodes()} or it can be constructed using either
2929
* {@link RedisClusterNode#getHost() host} and {@link RedisClusterNode#getPort()} or the {@link RedisClusterNode#getId()
3030
* node Id}.
31+
* <p>
32+
* {@link RedisClusterConnection Redis connections}, unlike perhaps their underlying native connection are not
33+
* Thread-safe and should not be shared across multiple threads.
3134
*
3235
* @author Christoph Strobl
3336
* @author Mark Paluch

Diff for: src/main/java/org/springframework/data/redis/connection/RedisConnection.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@
2020
import org.springframework.dao.DataAccessException;
2121

2222
/**
23-
* A connection to a Redis server. Acts as an common abstraction across various Redis client libraries (or drivers).
23+
* A connection to a Redis server. Acts as an common abstraction across various Redis client libraries (or
24+
* drivers).
2425
* Additionally performs exception translation between the underlying Redis client library and Spring DAO exceptions.
2526
* The methods follow as much as possible the Redis names and conventions.
2627
* <p>
27-
* Spring Data Redis {@link RedisConnection connections}, unlike perhaps their underlying native connection (for example:
28-
* the Lettuce {@literal StatefulRedisConnection}) are not Thread-safe. Please refer to the corresponding the Javadoc
29-
* for Redis client library (driver) specific connections provided by Spring Data Redis for more details.
28+
* {@link RedisConnection Redis connections}, unlike perhaps their underlying native connection are not Thread-safe and
29+
* should not be shared across multiple threads.
3030
*
3131
* @author Costin Leau
3232
* @author Christoph Strobl

Diff for: src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535

3636
import org.apache.commons.logging.Log;
3737
import org.apache.commons.logging.LogFactory;
38-
3938
import org.springframework.beans.DirectFieldAccessor;
4039
import org.springframework.beans.PropertyAccessor;
4140
import org.springframework.dao.DataAccessException;
@@ -61,6 +60,8 @@
6160
* {@link RedisClusterConnection} implementation on top of {@link JedisCluster}.<br/>
6261
* Uses the native {@link JedisCluster} api where possible and falls back to direct node communication using
6362
* {@link Jedis} where needed.
63+
* <p>
64+
* This class is not Thread-safe and instances should not be shared across threads.
6465
*
6566
* @author Christoph Strobl
6667
* @author Mark Paluch

Diff for: src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java

+1-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141

4242
import org.apache.commons.logging.Log;
4343
import org.apache.commons.logging.LogFactory;
44-
4544
import org.springframework.core.convert.converter.Converter;
4645
import org.springframework.dao.DataAccessException;
4746
import org.springframework.dao.InvalidDataAccessApiUsageException;
@@ -60,10 +59,7 @@
6059
/**
6160
* {@code RedisConnection} implementation on top of <a href="https://github.com/redis/jedis">Jedis</a> library.
6261
* <p>
63-
* WARNING: The {@link JedisConnection} class is not Thread-safe. This class requires and uses a
64-
* {@literal Jedis} instance from the Jedis client library (driver), which is very clearly
65-
* <a href="https://github.com/redis/jedis/wiki/Getting-started#using-jedis-in-a-multithreaded-environment">documented</a>
66-
* as not Thread-safe.
62+
* This class is not Thread-safe and instances should not be shared across threads.
6763
*
6864
* @author Costin Leau
6965
* @author Jennifer Hickey

Diff for: src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java

+5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@
7575
* <p>
7676
* This connection factory must be {@link #afterPropertiesSet() initialized} prior to {@link #getConnection obtaining
7777
* connections}.
78+
* <p>
79+
* Note that {@link JedisConnection} and its {@link JedisClusterConnection clustered variant} are not Thread-safe and
80+
* instances should not be shared across threads. Refer to the
81+
* <a href="https://github.com/redis/jedis/wiki/Getting-started#using-jedis-in-a-multithreaded-environment">Jedis
82+
* documentation</a> for guidance on configuring Jedis in a multithreaded environment.
7883
*
7984
* @author Costin Leau
8085
* @author Thomas Darimont

Diff for: src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
import org.apache.commons.logging.Log;
3434
import org.apache.commons.logging.LogFactory;
35-
3635
import org.springframework.beans.factory.DisposableBean;
3736
import org.springframework.dao.DataAccessException;
3837
import org.springframework.dao.InvalidDataAccessApiUsageException;
@@ -53,6 +52,13 @@
5352
/**
5453
* {@code RedisClusterConnection} implementation on top of <a href="https://github.com/mp911de/lettuce">Lettuce</a>
5554
* Redis client.
55+
* <p>
56+
* While the underlying Lettuce {@literal RedisClient} and {@literal StatefulRedisConnection} instances used by
57+
* {@link LettuceClusterConnection} are Thread-safe, this class itself is not Thread-safe. Therefore, instances of
58+
* {@link LettuceClusterConnection} should not be shared across multiple Threads when executing Redis commands and other
59+
* operations. If optimal performance is required by your application(s), then we recommend direct access to the
60+
* low-level, API provided by the underlying Lettuce client library (driver), where such Thread-safety guarantees can be
61+
* made. Simply call {@link #getNativeConnection()} and use the native resource as required.
5662
*
5763
* @author Christoph Strobl
5864
* @author Mark Paluch
@@ -486,7 +492,6 @@ public void multi() {
486492
throw new InvalidDataAccessApiUsageException("MULTI is currently not supported in cluster mode");
487493
}
488494

489-
490495
public ClusterCommandExecutor getClusterCommandExecutor() {
491496
return clusterCommandExecutor;
492497
}

Diff for: src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@
8080
* {@code RedisConnection} implementation on top of <a href="https://github.com/mp911de/lettuce">Lettuce</a> Redis
8181
* client.
8282
* <p>
83-
* WARNING: While the underlying Lettuce {@literal RedisClient} and {@literal StatefulRedisConnection} instances used by
84-
* {@link LettuceConnection} are Thread-safe, this class itself is not Thread-safe. Therefore, instances of {@link LettuceConnection}
85-
* should not be shared across multiple Threads when executing Redis commands and other operations. If optimal performance
86-
* is required by your application(s), then we recommend direct access to the low-level, API provided by the underlying
87-
* Lettuce client library (driver), where such Thread-safety guarantees can be made. Simply call {@link #getNativeConnection()}
88-
* and use the native resource as required.
83+
* While the underlying Lettuce {@literal RedisClient} and {@literal StatefulRedisConnection} instances used by
84+
* {@link LettuceConnection} are Thread-safe, this class itself is not Thread-safe. Therefore, instances of
85+
* {@link LettuceConnection} should not be shared across multiple Threads when executing Redis commands and other
86+
* operations. If optimal performance is required by your application(s), then we recommend direct access to the
87+
* low-level, API provided by the underlying Lettuce client library (driver), where such Thread-safety guarantees can be
88+
* made. Simply call {@link #getNativeConnection()} and use the native resource as required.
8989
*
9090
* @author Costin Leau
9191
* @author Jennifer Hickey

Diff for: src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@
6868
/**
6969
* Connection factory creating <a href="https://github.com/mp911de/lettuce">Lettuce</a>-based connections.
7070
* <p>
71-
* This factory creates a new {@link LettuceConnection} on each call to {@link #getConnection()}. Multiple
72-
* {@link LettuceConnection}s share a single thread-safe native connection by default.
71+
* This factory creates a new {@link LettuceConnection} on each call to {@link #getConnection()}. While multiple
72+
* {@link LettuceConnection}s share a single thread-safe native connection by default, {@link LettuceConnection} and its
73+
* {@link LettuceClusterConnection clustered variant} are not Thread-safe and instances should not be shared across
74+
* threads.
7375
* <p>
7476
* The shared native connection is never closed by {@link LettuceConnection}, therefore it is not validated by default
7577
* on {@link #getConnection()}. Use {@link #setValidateConnection(boolean)} to change this behavior if necessary. If

0 commit comments

Comments
 (0)