Redis transaction-depth analysis and use

As a relational database in a very important basic functions - the transaction, in Redis is how to handle and use?

1 Introduction

A transaction is to provide a multiple commands packaging, disposable mechanism sequentially executed, and ensure that the server only after completion of all the commands in the transaction, will continue to process other commands this client.
Affairs but also in other relational databases, a very important capability are essential. To the scene to pay, for example, only after the completion of normal consumption under normal circumstances, only minus the account balance. But if there is no guarantee a transaction, the consumer may occur failed, but still will account balance to be deducted, and I think this case should be that no one can accept it? Therefore, the transaction is a relational database in a very important basic functions.

2. Use basic affairs

Services in other languages ​​is generally performed process is divided into three phases:

  • Open affairs --Begin Transaction
  • Business code execution, the transaction is committed --Common Transaction
  • Abnormal, roll back the transaction --Rollback Transaction Processing business appears

Java to execute the transaction as an example:

// 开启事务
begin();
try {
    //......
    // 提交事务
    commit();
} catch(Exception e) {
    // 回滚事务
    rollback();
}

Redis in transactions from start to finish is to go through three stages:

  • Open affairs
  • Command into the column
  • The enforcement branch / abort the transaction

Among them, the use of open transaction multi command, the transaction performed using the exec command to abandon the transaction using the discard command.

1) open affairs

multi Command to enable transaction codes are as follows:

> multi
OK

multi Command allows clients from non-transactional mode state, the state becomes the transaction mode, as shown below:
image.png
Note : multi command can not be nested, if the case has opened the transaction, and then execute multithe command will prompt the following error:

(error) ERR MULTI calls can not be nested

Implementation of the results, as shown in the following code:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> multi
(error) ERR MULTI calls can not be nested

When a non-client transaction state using multi a command, the client returns a result OK , if the client has a transaction state, then execute  multi command multi command error can not be nested, but the client does not terminate the transaction state, as shown below It shows:
image.png

2) command enqueue

After the client enters the state of affairs, all routine operations Redis command execution (non-execution or give up and trigger a transaction that caused the exception into the column command) will turn into the column, the column after a successful command returns QUEUED , as shown in the following code:

> multi
OK
> set k v
QUEUED
> get k
QUEUED

Execution flow as shown below:
image.png
Note : column access command FIFO order (FIFO), that the transaction will follow the order of enqueued commands from front to back in sequence.

3) The enforcement branch / abandon Affairs

Command is executed transactions is exec to abandon the transaction command discard .
Sample code transaction performed as follows:

> multi
OK
> set k v2
QUEUED
> exec
1) OK
> get k
"v2"

Sample code to abandon the transaction as follows:

> multi
OK
> set k v3
QUEUED
> discard
OK
> get k
"v2"

Execution flow as shown below:
image.png

3. rollback transaction error &

Transaction execution errors are divided into the following three categories:

  • Error will occur when execute (referred to as: execution error);
  • When the error column, do not terminate the entire transaction;
  • When the column error will abort the whole transaction.

    1) When the execution error

    Sample code is as follows:
> 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"

Run explained as follows:
image.png
As can be seen from the above results, even when the transaction queue a command error occurs during execution, the transaction will proceed, until the transaction is completed executing all commands in the queue.

2) into the column error caused the end of the transaction

Sample code is as follows:

> get k
"v"
> multi
OK
> set k v2
QUEUED
> multi
(error) ERR MULTI calls can not be nested
> exec
1) OK
> get k
"v2"

Execute the command interpreter shown below:
image.png
As can be seen, repeated execution multi will lead into the wrong column, but does not terminate the transaction, the results of the final query is executed transaction a success. In addition to repeat the multi command, as well as performed in the state of affairs watch is the same effect, the following will explain in detail about watch the content.

3) into the column error does not cause the end of the transaction

Sample code is as follows:

> 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"

Run explained as follows:
image.png

4) Why do not support transaction rollback?

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 并未正常执行。
执行流程如下图所示:
image.png
注意watch 命令只能在客户端开启事务之前执行,在事务中执行 watch 命令会引发错误,但不会造成整个事务失败,如下代码所示:

> multi
OK
> set k v3
QUEUED
> watch k
(error) ERR WATCH inside MULTI is not allowed
> exec
1) OK
> get k
"v3"

执行命令解释如下图所示:
image.png
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 事务相关的命令有以下五个:

  • multi:开启事务
  • exec:执行事务
  • discard:丢弃事务
  • watch:为事务提供乐观锁实现
  • unwatch:取消监控(取消事务中的乐观锁)

Redis transaction is divided into three phases under normal circumstances: Turn affairs, command the column, the enforcement branch. Redis transaction does not support the erroneous transaction rollback operation, but some of the columns in error, as set keyor watchwhen the monitored item is modified to provide the entire transaction rollback function.

7. Questions

Redis transaction concurrent modification of how to solve the problem? Redis transaction rollback support it? Which three errors occur when using Redis transaction? What is the impact of these three errors affairs? Only experts can answer the question, you can answer it a few?

8. Reference & Acknowledgment

https://redis.io/topics/transactions

https://redisbook.readthedocs.io/en/latest/feature/transaction.html#id3

Guess you like

Origin www.cnblogs.com/vipstone/p/11755496.html