Как использовать транзакции в Spring Data Redis Reactive?

Я пытаюсь использовать ReactiveRedisOperations из spring-data-redis 2.1.8 для выполнения транзакций, например:

WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC

Но я не могу найти способ сделать это при просмотре документы или ReactiveRedisOperations. Это недоступно в реактивном клиенте или как вы можете этого добиться?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
2 549
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

TL;DR: нет надлежащей поддержки транзакций Redis с использованием Reactive API.

Причина кроется в модели выполнения: как Redis выполняет транзакции и как должен работать реактивный API.

При использовании транзакций соединение переходит в транзакционное состояние, затем команды ставятся в очередь и, наконец, выполняются с помощью EXEC. Выполнение команд в очереди с помощью exec делает выполнение отдельных команд зависимым от команды EXEC.

Рассмотрим следующий фрагмент (код салата):

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();
        });

Обходной путь может включать подписку на команды в вашем коде (внимание: это антишаблон в реактивном программировании). Позвонив exec(), вы получите TransactionResult взамен.

Также обратите внимание: хотя вы можете получить результаты с помощью Mono<TransactionResult>, фактическая команда SET также выдает свой результат (см. doOnNext(…)).

При этом это позволяет нам вернуться к фактическому вопросу: поскольку эти концепции плохо работают вместе, в Spring Data Redis нет API для транзакционного использования.

Нельзя ли решить антипаттерн «плавающая подписка», просто используя Mono.when?var command = commands.set("key", "value").doOnNext(…), а затем return Mono.when(commands.exec(), command)? И с учетом сказанного я не могу найти multi как метод в Spring Boot 2.4.1, он был удален?

danthonywalker 09.01.2021 19:02

Другие вопросы по теме