Skip to content

Commit c4cba7f

Browse files
mp911dechristophstrobl
authored andcommitted
DATAREDIS-891 - Revise RedisConnection transaction/closure resource binding.
We now correctly consider the transactional state along with the requested bindings scope when binding RedisConnection for reuse. Previously, enabling transaction support on RedisTemplate registered the connection unconditionally with TransactionSynchronizationManager expecting a TransactionManager to close/unbind the connection upon transaction cleanup. This behavior could easily lead to lingering connections when a transactional RedisTemplate was used outside of a managed transaction. We now distinguish between closure-scope binding and transaction binding. Closure-scoped bindings (RedisTemplate.execute(SessionCallback)) do not interfere with transactional resources if there's no transactionally bound RedisConnection. Closure-scope however reuses a transactionally bound connection. Transaction-scoped binding binds only a connection to the transaction if there's an active transaction. Without an ongoing transaction, RedisTemplate does no longer bind connections to TransactionSynchronizationManager. Original Pull Request: #573
1 parent b14866c commit c4cba7f

File tree

6 files changed

+534
-164
lines changed

6 files changed

+534
-164
lines changed

src/main/asciidoc/reference/redis-transactions.adoc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[[tx]]
22
= Redis Transactions
33

4-
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.
4+
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.
55

6-
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:
6+
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

88
[source,java]
99
----
@@ -20,14 +20,23 @@ List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>
2020
System.out.println("Number of items added to set: " + txResults.get(0));
2121
----
2222

23-
`RedisTemplate` uses its value, hash key, and hash value serializers to deserialize all results of `exec` before returning. There is an additional `exec` method that lets you pass a custom serializer for transaction results.
23+
`RedisTemplate` uses its value, hash key, and hash value serializers to deserialize all results of `exec` before returning.There is an additional `exec` method that lets you pass a custom serializer for transaction results.
2424

2525
include::version-note.adoc[]
2626

2727
[[tx.spring]]
2828
== @Transactional Support
2929

30-
By default, transaction Support is disabled and has to be explicitly enabled for each `RedisTemplate` in use by setting `setEnableTransactionSupport(true)`. Doing so forces binding the current `RedisConnection` to the current `Thread` that is triggering `MULTI`. If the transaction finishes without errors, `EXEC` is called. Otherwise `DISCARD` is called. Once in `MULTI`, `RedisConnection` queues write operations. All `readonly` operations, such as `KEYS`, are piped to a fresh (non-thread-bound) `RedisConnection`.
30+
By default, `RedisTemplate` does not participate in managed Spring transactions.
31+
If you want `RedisTemplate` to make use of Redis transaction when using `@Transactional` or `TransactionTemplate`, you need to be explicitly enable transaction support for each `RedisTemplate` by setting `setEnableTransactionSupport(true)`.
32+
Enabling transaction support binds `RedisConnection` to the current transaction backed by a `ThreadLocal`.
33+
If the transaction finishes without errors, the Redis transaction gets commited with `EXEC`, otherwise rolled back with `DISCARD`.
34+
Redis transactions are batch-oriented.
35+
Commands issued during an ongoing transaction are queued and only applied when committing the transaction.
36+
37+
Spring Data Redis distinguishes between read-only and write commands in an ongoing transaction.
38+
Read-only commands, such as `KEYS`, are piped to a fresh (non-thread-bound) `RedisConnection` to allow reads.
39+
Write commands are queued by `RedisTemplate` and applied upon commit.
3140

3241
The following example shows how to configure transaction management:
3342

@@ -65,7 +74,7 @@ public class RedisTxContextConfiguration {
6574
----
6675
<1> Configures a Spring Context to enable https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#transaction-declarative[declarative transaction management].
6776
<2> Configures `RedisTemplate` to participate in transactions by binding connections to the current thread.
68-
<3> Transaction management requires a `PlatformTransactionManager`. Spring Data Redis does not ship with a `PlatformTransactionManager` implementation. Assuming your application uses JDBC, Spring Data Redis can participate in transactions by using existing transaction managers.
77+
<3> Transaction management requires a `PlatformTransactionManager`.Spring Data Redis does not ship with a `PlatformTransactionManager` implementation.Assuming your application uses JDBC, Spring Data Redis can participate in transactions by using existing transaction managers.
6978
====
7079

7180
The following examples each demonstrate a usage constraint:

0 commit comments

Comments
 (0)