如何在 Spring Data Redis Reactive 中使用事务?
How do I use transactions in Spring Data Redis Reactive?
我正在尝试使用 spring-data-redis 2.1.8 中的 ReactiveRedisOperations
进行交易,例如:
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
但在浏览 docs 或 ReactiveRedisOperations
时,我似乎无法找到执行此操作的方法。这在反应式客户端中不可用,还是如何实现?
TL;DR:没有对使用 Reactive API
的 Redis 事务的适当支持
原因在于执行模型:Redis 如何执行事务以及反应式 API 应该如何工作。
使用事务时,连接进入事务状态,然后命令排队并最终执行 EXEC
。使用 exec 执行排队的命令会使单个命令的执行以 EXEC
命令为条件。
考虑以下代码片段(Lettuce 代码):
RedisReactiveCommands<String, String> commands = …;
commands.multi().then(commands.set("key", "value")).then(commands.exec());
此序列以某种线性方式显示命令调用:
- 问题
MULTI
MULTI
完成后,发出 SET
命令
SET
完成后,调用 EXEC
关于 SET
的警告:SET
仅在调用 EXEC
后完成。所以这意味着我们有一个对 exec 命令的前向引用。我们无法监听将来要执行的命令。
您可以应用解决方法:
RedisReactiveCommands<String, String> commands = …
Mono<TransactionResult> tx = commands.multi()
.flatMap(ignore -> {
commands.set("key", "value").doOnNext(…).subscribe();
return commands.exec();
});
解决方法是将命令订阅合并到您的代码中(注意:这是反应式编程中的 anti-pattern)。调用 exec()
后,您会在 return.
中得到 TransactionResult
另请注意:虽然您可以通过 Mono<TransactionResult>
检索结果,但实际的 SET
命令也会发出其结果(请参阅 doOnNext(…)
)。
话虽如此,它让我们回到了实际问题:因为这些概念不能很好地协同工作,所以 Spring Data Redis 中没有用于事务的 API。
我正在尝试使用 spring-data-redis 2.1.8 中的 ReactiveRedisOperations
进行交易,例如:
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
但在浏览 docs 或 ReactiveRedisOperations
时,我似乎无法找到执行此操作的方法。这在反应式客户端中不可用,还是如何实现?
TL;DR:没有对使用 Reactive API
的 Redis 事务的适当支持原因在于执行模型:Redis 如何执行事务以及反应式 API 应该如何工作。
使用事务时,连接进入事务状态,然后命令排队并最终执行 EXEC
。使用 exec 执行排队的命令会使单个命令的执行以 EXEC
命令为条件。
考虑以下代码片段(Lettuce 代码):
RedisReactiveCommands<String, String> commands = …;
commands.multi().then(commands.set("key", "value")).then(commands.exec());
此序列以某种线性方式显示命令调用:
- 问题
MULTI
MULTI
完成后,发出SET
命令SET
完成后,调用EXEC
关于 SET
的警告:SET
仅在调用 EXEC
后完成。所以这意味着我们有一个对 exec 命令的前向引用。我们无法监听将来要执行的命令。
您可以应用解决方法:
RedisReactiveCommands<String, String> commands = …
Mono<TransactionResult> tx = commands.multi()
.flatMap(ignore -> {
commands.set("key", "value").doOnNext(…).subscribe();
return commands.exec();
});
解决方法是将命令订阅合并到您的代码中(注意:这是反应式编程中的 anti-pattern)。调用 exec()
后,您会在 return.
TransactionResult
另请注意:虽然您可以通过 Mono<TransactionResult>
检索结果,但实际的 SET
命令也会发出其结果(请参阅 doOnNext(…)
)。
话虽如此,它让我们回到了实际问题:因为这些概念不能很好地协同工作,所以 Spring Data Redis 中没有用于事务的 API。