如何在 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

但在浏览 docsReactiveRedisOperations 时,我似乎无法找到执行此操作的方法。这在反应式客户端中不可用,还是如何实现?

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。