Как очень важная базовая функция в реляционной базе данных — транзакция, как она обрабатывается и используется в Redis?
1. Введение
Транзакция относится к предоставлению механизма для упаковки нескольких команд и их последовательного одновременного выполнения, а также для обеспечения того, чтобы сервер продолжал обрабатывать другие команды этого клиента только после того, как все команды в транзакции были выполнены.
Транзакции также являются очень важной возможностью для других реляционных баз данных. Взяв в качестве примера сценарий оплаты, при нормальных обстоятельствах баланс счета будет вычтен только после завершения нормального потребления. Однако, если нет гарантии транзакции, потребление может не состояться, но остаток на счете все равно будет списан.Я думаю, что такая ситуация не должна быть приемлемой ни для кого, верно? Таким образом, транзакция является очень важной базовой функцией в базе данных.
2. Основное использование бизнеса
В других языках транзакции обычно делятся на следующие три этапа:
- Открыть транзакцию - Начать транзакцию
- Выполнение бизнес-кода и отправка транзакции — обычная транзакция
- В бизнес-обработке возникает исключение, и транзакция откатывается — Rollback Transaction
В качестве примера возьмем выполнение транзакции в Java:
// 开启事务
begin();
try {
//......
// 提交事务
commit();
} catch(Exception e) {
// 回滚事务
rollback();
}
Транзакции в Redis также проходят три этапа от начала до конца:
- открытая транзакция
- поставить команду в очередь
- выполнить транзакцию/отказаться от транзакции
Среди них использование открытых транзакцийmulti
команда, выполнение транзакции используетexec
команда, отказаться от использования транзакцииdiscard
Заказ.
1) Открыть транзакцию
multi
Команда используется для запуска транзакции, и код реализации выглядит следующим образом:
> multi
OK
multi
Команда позволяет клиенту перейти из состояния нетранзакционного режима в состояние транзакционного режима, как показано на следующем рисунке:
multi
команда, это вызовет следующую ошибку:
(error) ERR MULTI calls can not be nested
Эффект выполнения показан в следующем коде:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> multi
(error) ERR MULTI calls can not be nested
Когда клиент находится в нетранзакционном состоянии, используйтеmulti
команда, клиент вернет результатOK
, если клиент уже находится в состоянии транзакции, выполнить сноваmulti
командное совещаниеmulti
Команды не могут быть вложены для ошибок, но не завершат работу клиента из-за транзакционного состояния, как показано на следующем рисунке:
2) запись заказа
После того, как клиент входит в состояние транзакции, все обычные выполняемые команды операций Redis (команды, которые не запускают выполнение транзакции или не прекращают выполнение и не вызывают постановку в очередь исключения) будут последовательно поставлены в очередь и вернутся после успешной постановки команды в очередь.QUEUED
, как показано в следующем коде:
> multi
OK
> set k v
QUEUED
> get k
QUEUED
Поток выполнения показан на следующем рисунке:
3) Выполнить транзакцию/отказаться от транзакции
Команда для выполнения транзакцииexec
, команда отказаться от транзакцииdiscard
.
Пример кода для выполнения транзакции выглядит следующим образом:
> multi
OK
> set k v2
QUEUED
> exec
1) OK
> get k
"v2"
Пример кода отказа от транзакции выглядит следующим образом:
> multi
OK
> set k v3
QUEUED
> discard
OK
> get k
"v2"
Поток выполнения показан на следующем рисунке:
3. Ошибка транзакции и откат
Ошибки при выполнении транзакций делятся на следующие три категории:
- Ошибки, возникающие только во время выполнения (аббревиатура: ошибки времени выполнения);
- Ошибка при постановке в очередь не приведет к завершению всей транзакции;
- Ошибка в очереди остановит всю транзакцию.
1) Ошибка при выполнении
Пример кода выглядит следующим образом:
> get k
"v"
> multi
OK
> set k v2
QUEUED
> expire k 10s
QUEUED
> exec
1) OK
2) (error) ERR value is not an integer or out of range
> get k
"v2"
Команда выполнения поясняется, как показано на следующем рисунке:
2) Ошибки постановки в очередь не влияют на транзакции
Пример кода выглядит следующим образом:
> get k
"v"
> multi
OK
> set k v2
QUEUED
> multi
(error) ERR MULTI calls can not be nested
> exec
1) OK
> get k
"v2"
Команда выполнения поясняется, как показано на следующем рисунке:
multi
Вызовет ошибку постановки в очередь, но не завершит транзакцию, а конечным результатом запроса будет то, что транзакция выполнена успешно. Кроме повтораmulti
Команды и выполнение в транзакционном состоянииwatch
Это тоже тот самый эффект, который будет подробно объяснен ниже.watch
Содержание.
3) Ошибка ввода приводит к завершению транзакции
Пример кода выглядит следующим образом:
> get k
"v2"
> multi
OK
> set k v3
QUEUED
> set k
(error) ERR wrong number of arguments for 'set' command
> exec
(error) EXECABORT Transaction discarded because of previous errors.
> get k
"v2"
Команда выполнения поясняется, как показано на следующем рисунке:
4) Почему не поддерживается откат транзакций?
Официальная документация Redis объясняет это следующим образом:
If you have a relational databases background, the fact that Redis commands can fail during a transaction, but still Redis will execute the rest of the transaction instead of rolling back, may look odd to you. However there are good opinions for this behavior:
- Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.
- Redis is internally simplified and faster because it does not need the ability to roll back. An argument against Redis point of view is that bugs happen, however it should be noted that in general the roll back does not save you from programming errors. For instance if a query increments a key by 2 instead of 1, or increments the wrong key, there is no way for a rollback mechanism to help. Given that no one can save the programmer from his or her errors, and that the kind of errors required for a Redis command to fail are unlikely to enter in production, we selected the simpler and faster approach of not supporting roll backs on errors.
Это примерно означает, что автор не поддерживает откат транзакций по следующим двум причинам:
- Он считает, что при выполнении транзакций Redis ошибки обычно вызваны ошибками программирования.Такие ошибки обычно появляются только в среде разработки и редко появляются в реальной производственной среде, поэтому он считает, что нет необходимости разрабатывать транзакции для Redis. функция;
- Откат транзакций не поддерживается, поскольку эта сложная функция не соответствует простой и эффективной теме дизайна, которой придерживается Redis.
Откат транзакций здесь не поддерживается, что означает, что откат транзакций ошибок времени выполнения не поддерживается.
4. Мониторинг
watch
Команда используется для обеспечения оптимистической блокировки (CAS, Check And Set) для транзакции, когда клиент является параллельным, то есть вы можете использоватьwatch
команда для мониторинга одной или нескольких переменных, если в ходе транзакцииЭлемент мониторинга изменен, тогдався транзакциябудетпрекратить выполнение.watch
Основной синтаксис следующий:
watch key [key ...]
watch
Пример кода выглядит следующим образом:
> watch k
OK
> multi
OK
> set k v2
QUEUED
> exec
(nil)
> get k
"v"
Как видно из приведенной выше команды, еслиexec
Возвращаемый результатnil
когда, указываяwatch
Отслеживаемый объект был изменен во время выполнения транзакции. отget k
В результате также видно, что значение, установленное в транзакцииset k v2
Не работает должным образом.
Поток выполнения показан на следующем рисунке:
watch
Команды могут выполняться только до того, как клиент откроет транзакцию, и выполняться внутри транзакции.watch
Команда выдает ошибку, но не приводит к сбою всей транзакции, как показано в следующем коде:
> multi
OK
> set k v3
QUEUED
> watch k
(error) ERR WATCH inside MULTI is not allowed
> exec
1) OK
> get k
"v3"
Команда выполнения поясняется, как показано на следующем рисунке:
unwatch
Команда используется для очистки всех ранее отслеживаемых объектов (пар ключ-значение).unwatch
Пример выглядит так:
> set k v
OK
> watch k
OK
> multi
OK
> unwatch
QUEUED
> set k v2
QUEUED
> exec
1) OK
2) OK
> get k
"v2"
Видно, что даже во время выполнения транзакции значение k изменяется, поскольку вызовunwatch
команда, вся транзакция по-прежнему будет выполняться гладко.
5. Транзакции используются в программах
Ниже приведено использование транзакций в Java, код выглядит следующим образом:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class TransactionExample {
public static void main(String[] args) {
// 创建 Redis 连接
Jedis jedis = new Jedis("xxx.xxx.xxx.xxx", 6379);
// 设置 Redis 密码
jedis.auth("xxx");
// 设置键值
jedis.set("k", "v");
// 开启监视 watch
jedis.watch("k");
// 开始事务
Transaction tx = jedis.multi();
// 命令入列
tx.set("k", "v2");
// 执行事务
tx.exec();
System.out.println(jedis.get("k"));
jedis.close();
}
}
6. Резюме
Транзакции предоставляют механизм для последовательного одновременного выполнения нескольких команд.Существует пять команд, связанных с транзакциями Redis:
- мульти: открытая транзакция
- exec: выполнить транзакцию
- discard: отменить транзакцию
- watch: Обеспечивает реализацию оптимистичной блокировки для транзакций.
- unwatch: отменить мониторинг (отменить оптимистичные блокировки в транзакциях)
В обычных условиях транзакция Redis делится на три этапа: открытие транзакции, постановка команды в очередь и выполнение транзакции. Транзакции Redis не поддерживают откат транзакций для ошибок времени выполнения, но при некоторых ошибках в очереди, таких какset key
илиwatch
Когда элемент мониторинга изменяется, он обеспечивает функцию отката всей транзакции.
7. Вопросы для размышления
Как решить проблему одновременной модификации в транзакции Redis? Поддерживает ли Redis откат транзакций? Какие три типа ошибок могут возникнуть при использовании транзакций Redis? Как эти три ошибки влияют на транзакции? Вопросы, на которые правильно могут ответить только специалисты, на сколько сможете ответить вы?
8. Ссылки и благодарности
Redis book.Прочитайте документ S.IO/en/latest/post…
Следуйте QR-коду ниже, чтобы подписаться на более интересный контент