preface

A few days ago, a reader said that he was asked about Redis affairs in an interview. Although it is not often used, he was asked about Redis affairs in an interview. Usually, HE did not pay attention to this part of Redis affairs, and it was very uncomfortable when he was asked about it in an interview.

Although the reader passed the interview, he did not get the salary he wanted.

In fact, this is normal, the general interview is asked the street, who also ask you ah, specifically pick some unusual to ask you, in order to pressure your salary.

Therefore, I would like to write an article here to explain the Redis transaction in detail. It is estimated that it is enough to understand the Redis transaction from the principle to the depth of this article.

In future interviews, you will not have to worry about being asked about Redis affairs again. This article mainly explains the principles and practical exercises of Redis affairs. While understanding the theory, it also proves the theory by practical practice.

The transaction is introduced

A Redis transaction is a collection of commands. Multiple commands are packaged and then queued sequentially and executed sequentially.

“Redis transactions do not have the same concept of transaction isolation level as Mysql relational databases, atomicity is not guaranteed, and there is no rollback operation like Mysql when a transaction fails.”

This is closely related to Redis’s “fast and efficient” feature, “because some of the rollback operations, locking and unlocking such as transaction isolation levels, are performance intensive”. Therefore, the process of executing transactions in Redis requires only the following three simple steps:

  1. Start transaction (MULTI)
  2. The command team
  3. Transaction execution (EXEC), Transaction cancellation (DISCARD)

Transactions in Redis are implemented mainly through the following commands:

The command Functional description
MULTI The command to start a transactionAfter this command is executed, the following commands are used to query the data type of the RedisOperation commands are queued sequentiallyThe commands in the queue are executed only after the EXEC command is executed
DISCARD Discard the command in the queue, which you can understand as Mysql’s rollback operation,And change the current state from transactional to non-transactional.
EXEC After the command is executedIndicates that the commands in the queue are executed sequentially, and display the result in the client,Change the current state from transactional to non-transactional. If a key is executed by the WATCH command and modified by other clients before executing this command, all commands in the execution queue will be abandoned and error information will be displayed on the client. If there is no modification, all commands in the queue will be executed.
WATCH key Specifies a key to monitor,This command can be executed only before the MULTI commandIf the monitored key is modified by another client,EXEC will discard all commands in the execution queue
UNWATCH The key monitored by the WATCH command before canceling the monitoring, the key monitored before the EXEC and DISCARD commands will also be unmonitored

These are the commands included in the execution process of a Redis transaction. The following is a detailed explanation of these commands.

Start the transaction

MULTIThe “OK” command indicates the start of the transaction, and the “OK” command indicates that the transaction has entered the state:After this command is executed, the client willThe current state is changed from non-transactional to transactional, this state switch is going to the clientflagsPropertyREDIS_MULTIThis command can understand the relational database MysqlBEGIN TRANCATIONStatement:

The command team

After the MULTI command is executed, the following five types of Redis commands are entered into the command queue in sequence, which is also the part of real business logic.

If the current state of the Redis client is in the transaction state, the command will be queued and returnedQUEUEDA string indicating that the command has entered the command queue andA transaction queue holds queued commands in a first-in, first-out (FIFO) manner.If the current state is non-transactional, the command is executed immediately and the result is returned to the client. In transaction stateThe command to execute the operation transaction is executed immediately, such asEXEC, DISCARD, UNWATCH.Combined with the above analysis, the command execution process of Redis is shown in the figure below:The three parameters in the transaction command queue are:The command to be executed,Command parameters,Number of parameters. For example, run the following command:

redis> MULTI
OK
redis> SET name "Li Du"
QUEUED
redis> GET name
QUEUED Copy the code

The three parameters corresponding to the above queue are shown in the table below:

Executed command Command parameters Number of parameters
SET [“name”, “Lidu “] 2
GET [“name”] 1

Perform transactions

When the client executes the EXEC command, the above command queue is executed in a first-in, first-out (FIFO) order. Of course, the execution results are mixed, which will be analyzed later.

As mentioned above, commands sent to the server are executed immediately if the client is in a non-transactional state, and are queued if the client is in a transactional state.

When commands are added to the queue, they are added to the queue in sequence. The commands in the queue are executed on a first-in, first-out basis.

If the client is in the transactional state, the execution isEXEC, DISCARD, UNWATCHThe commands that operate on transactions are also executed immediately.(1) Normal execution

As in the above example, execute the following code:

redis> MULTI
OK
redis> SET name "Li Du"
QUEUED
redis> GET name
QUEUED Copy the code

All commands enter the queue. When EXEC is executed at the end, SET command will be executed first, then GET command will be executed, and the results after execution will also be stored in a queue, and finally returned to the client:

Type of reply Content of reply
status code reply OK
bulk reply “Li Du”

So in the end you will see “OK, lidu” on the client, which will indicate that this is the process of a transaction executing successfully.

At this point a transaction is fully executed and the client changes from a transactional state to a non-transactional state.

(2) Discard the transaction

Of course, you can DISCARD the transaction, as long as you DISCARD again will abandon the transaction. The specific code is as follows:

redis> MULTI
OK
redis> SET name "Li Du"
QUEUED
redis> GET name
QUEUED Redis > DISCARD // DISCARD the transactionOK Copy the code

When the DISCARD command is used to cancel a transaction, the command queue is cleared and the client state is changed from transaction to non-transaction.

“Redis transactions are not repeatable”, when the client is in a transactional state, sending the MULTI command again to the server will directly return an error to the client.

WATCH command

The WATCH command is executed before the MULTI command, indicating that any number of keys are monitored. The corresponding command is the UNWATCH command, which is the key to cancel the monitoring.

The WATCH command is “similar to optimistic locking mechanism”. If any of the monitored keys are changed during transaction execution, the command in the queue will not be executed and will return (nil) to the client to indicate transaction failure.

Now let’s demonstrate the operation process of the WATCH command. The specific implementation code is as follows:

redis> WATCH num
OK
redis> MULTI
OK
redis> incrby num 10
QUEUED redis> decrby num 1 QUEUED Redis > EXEC // The execution succeededCopy the code

This is the normal operation flow of the WATCH command. If any monitored key is changed in another client, the transaction will be abandoned, as shown in the figure below:

The client a Client 2
WATCH num
MULTI
incrby num 10 get num
decrby num 1
EXEC
Failed execution, return nil.

In the underlying implementation of the WATCH commandwatched_keysThe dictionary,The key of the dictionary holds the key to monitor, and the value is a linked list. Each node value in the list holds the client that monitors the key.If a client stops monitoring a key, the client will disassociate from the list. For example, in client3, key1 is no longer monitored by executing UNWATCH:

Error handling

As mentioned above, Redis does not have a rollback mechanism. In the process of execution, if the command of Redis is accidentally typed, the command sent to the server is not executed immediately, so the error is not found temporarily.

Then error handling in Redis can be divided into two categories: “syntax error” and “running error”. Here’s the main difference between these two types of errors.

(1) Syntax error

For example, when executing a command, the command does not exist, the wrong command is typed, and the number of parameters is not equal, which will lead to syntax errors.

To demonstrate, execute the following four commands. The first two are correct and the second two are incorrect, as shown below:

127.0.0.1:6379 > multiOK
127.0.0.1:6379 >set num 1
QUEUED
127.0.0.1:6379 >set num
(error) ERR wrong number of arguments for 'set' command 127.0.0.1:6379 > ssset num 3(error) ERR unknown command 'ssset' 127.0.0.1:6379 >set num 2 QUEUED 127.0.0.1:6379 >exec (error) EXECABORT Transaction discarded because of previous errors. Copy the code

Syntax errors are found during Redis syntax detection, so when you execute incorrect commands, you will return an error message.

Finally, even if the command enters the queue, as long as there is a syntax error, the commands in the queue will not be executed, and the prompt of transaction execution failure will be returned directly to the client.

(2) Running error

When different types of operation commands are used to operate on different data types, runtime errors will occur, which Redis will not be able to detect if the command is not executed.

127.0.0.1:6379 > multiOK
127.0.0.1:6379 >set num 3
QUEUED
127.0.0.1:6379 > sadd num 4QUEUED 127.0.0.1:6379 >set num 6 QUEUED 127.0.0.1:6379 >exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 3) OK 127.0.0.1:6379 > get the key"6" Copy the code

As a result, the correct command is executed, but the wrong command is not not executed. This also shows that Redis transactions do not guarantee data consistency, because there are errors in the middle, and some statements are still executed.

This result can only be the programmer according to the previous execution of the command, his correct step by step back, the so-called own mess, their own cleaning up.

Redis transactions and Mysql transactions

We know that Mysql, a relational database, has four characteristics for transactions: “Atomicity, Consistency, Isolation, Durability”.

However, in order to ensure that Redis in addition to the client request efficiency, the traditional relational database “transaction rollback, lock, unlock” these performance consumption operations, Redis transaction implementation is simple.

In the atomicity of Redis transaction, only the atomicity of a single command can be guaranteed, while that of multiple commands cannot be guaranteed. For example, for the run-time error of the ropway above, even if there is a run-time error in the middle, the correct command will be correctly executed without rollback operation.

Since there is no atomicity, there is no guarantee of data consistency, and this needs to be implemented manually by the programmer.

Reids will not be interrupted until the end of a transaction, and Redis will persist data.