Транзакции в Redis
В этом руководстве по Redis мы узнаем, как ставить в очередь несколько команд для последующего выполнения с гарантированными транзакциями. Мы рассмотрим, как создавать очереди транзакций, выполнять команды в очереди, как очищать очередь и как обрабатывать ошибки транзакций.
Что такое транзакция Redis
Транзакция базы данных представляет собой любое изменение в базе данных, независимое от других транзакций.
Транзакции Redis позволяют нам ставить в очередь более одной операции, а затем выполнять их все с помощью одной команды.
Транзакции Redis выполняются с двумя важными гарантиями:
- Все команды в транзакции сериализуются и выполняются последовательно. Запрос от одного клиента не может быть обслужен, когда другой находится в процессе выполнения.
- Транзакции Redis являются атомарными, что означает, что обрабатываются либо все команды, либо ни одна из них.
Как создать транзакцию
Команда MULTI позволяет добавлять в очередь операции, которые будут выполняться позже при вызове команды выполнения.
В качестве примера предположим, что мы хотим получить значение ключа, выполнить вычисления по значению, а затем обновить ключ новым значением. Мы не хотим, чтобы какая-либо другая операция изменяла значение, пока мы не закончим наши вычисления.
У команды MULTI нет аргументов, и мы просто выполняем ее перед любыми другими командами, которые хотим поставить в очередь.
Синтаксис:
MULTI
Redis ответит подтверждением того, что следующие команды будут добавлены в очередь транзакций.
Вывод:
OK
Теперь мы можем добавлять команды в очередь.
Пример:
SET num-1 20
Redis добавит скрипт в очередь и снова вернет подтверждающее сообщение.
Вывод:
QUEUED
Мы можем сделать это с помощью нескольких команд
Пример:
INCR num-1 GET num-1 DECR num-1 GET num-1
Теперь все три команды поставлены в очередь на выполнение.
Как выполнять команды очереди транзакций
Чтобы выполнить стек команд в очереди в транзакции Redis, мы будем использовать команду EXEC . Эта команда без аргументов.
Синтаксис:
EXEC
Redis будет выполнять операции последовательно и возвращать массив с результатом каждой операции в той же последовательности, в которой команды были поставлены в очередь.
Вывод:
1) OK 2) (integer) 21 3) "21" 4) (integer) 20 5) "20"
Как очистить очередь транзакций
Если нам нужно очистить очередь транзакций, мы используем команду DISCARD. Эта команда не имеет аргументов.
Синтаксис:
DISCARD
Давайте создадим очередь транзакций, а затем очистим ее до выполнения
Пример:
MULTI INCR num-1 GET num-1 DISCARD
Если очередь была успешно очищена, Redis отправит подтверждающее сообщение.
Вывод:
OK
Если мы попытаемся выполнить транзакцию EXEC , она потерпит неудачу и отправит ошибку.
Вывод:
(error) ERR EXEC without MULTI
Если мы сейчас вернем значение 'num-1', мы увидим, что ничего не изменилось.
Вывод:
"20"
Как обрабатываются ошибки в транзакции
Мы можем столкнуться с двумя типами ошибок.
В качестве примера давайте рассмотрим, что мы пытаемся выполнить неправильный тип операции.
Пример:
MULTI SET msg "Hello" LPOP msg APPEND msg " World" EXEC
В приведенном выше примере мы пытаемся удалить элемент из списка с помощью LPOP , но ключ msg не является списком, поэтому операция завершится ошибкой.
Вывод:
1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 3) (integer) 11
Даже если одна команда не сработает, остальные все равно будут выполняться. Если мы ПОЛУЧИМ 'msg', мы увидим, что команда APPEND все еще выполняется.
Вывод:
"Hello World"
Другой тип ошибки — когда команда не может быть поставлена в очередь. Ошибка может возникнуть еще до вызова exec.
Например, команда может быть синтаксически неправильной.
Пример:
MULTI GET key value
В приведенном выше примере мы передаем неправильное количество аргументов команде GET .
Вывод:
(error) ERR wrong number of arguments for 'get' command
Мы все еще можем добавить больше элементов в очередь.
Пример:
SET msg "Hello There"
Вывод:
QUEUED
Но если мы попытаемся выполнить EXEC , Redis выдаст ошибку, потому что помнит, что в стеке был один.
Вывод:
(error) EXECABORT Transaction discarded because of previous errors.
В этом случае Redis автоматически ОТМЕНИТ транзакцию.