This is the 28th day of my participation in the August Challenge

Redis transactions

A Redis transaction is a collection of commands. All commands in a transaction are serialized and executed in sequence during the transaction! Unlike relational databases such as MySQL, Redis transactions have no concept of isolation levels, atomicity is not guaranteed, and transaction rollback is not supported.

Redis transaction command

  • Multi This command enables a transaction for display. After a transaction is enabled using this command, subsequent operation commands enter the execution queue corresponding to the transaction. After the Exec command is executed, the operation commands are executed in sequence.

  • Watch key [key …] The WATCH command is used to solve the problem of non-repeatable reads and phantom reads caused by concurrent transactions. This command is used to monitor an object and can be executed only before the MULTI command. If the monitored object has been modified by other clients, all action commands in the transaction execution queue will be discarded when the Exec command is executed and (nil) will be returned directly to the client indicating that the transaction has failed. (Watch can operate as an optimistic lock of Redis. Every time data is updated, it will determine whether the data has been modified during this period.)

  • Unwatch key [key …] Unmonitor an object

  • Exec This command is used to formally execute a transaction. After this command is invoked, all operation commands in the transaction queue are executed in sequence. If WATCH is called before the Exec command, the command is executed only if the object under monitoring is not modified, otherwise execution stops.

  • Discard This command is used to Discard operation commands in the transaction execution queue and change the current transaction state to non-transaction state. If the Watch command is invoked before this command, the Watch command releases monitored objects.

🚦 In general, Redis implements transactions through Multi(start transaction), command join and Exec(execute transaction) commands. The following example

127.0.0.1:6379(TX)> set key1 v1 QUEUED 127.0.0.1:6379(TX)> set key2 v2 127.0.0.1:6379(TX)> set key3 V3 127.0.0.1:6379(TX)> set key4 V4 127.0.0.1:6379(TX)> exec # execute transaction 1) OK 2) OK 3) OK 4) OKCopy the code

Cancel a transaction (discard), and the commands in the transaction queue will not be executed:

127.0.0.1:6379> multi 
OK 
127.0.0.1:6379(TX)> set key1 v1 
QUEUED 
127.0.0.1:6379(TX)> set key2 v2 
QUEUED 
127.0.0.1:6379(TX)> set key3 v3 
QUEUED 127.0.0.1:6379(TX)> discard 
OK 
127.0.0.1:6379> get key1 (nil) 
127.0.0.1:6379> get key2 (nil) 
127.0.0.1:6379> get key3 (nil)
Copy the code

Use the Watch command

The Watch command is executed before the Multi command to monitor any number of objects, and its counterpart is the Unwatcch command to unmonitor. The following is an example:

  • The following example simulates a transfer operation. Before the transaction starts, listen to the money object and determine whether the money has been modified during the money-20 operation.
127.0.0.1:6379> set money 100 OK 127.0.0.1:6379> set out 0 OK 127.0.0.1:6379> set out 0 OK 127.0.0.1:6379> Multi OK 127.0.0.1:6379(TX)> decrby money 20 QUEUED 127.0.0.1:6379(TX)> incrby out 20 QUEUED 127.0.0.1:6379(TX)> exec 1) (integer) 80 2) (INTEGER) 20 127.0.0.1:6379> Get moneyCopy the code
  • Let’s test multi-client, listen on the money object and modify the value on another client before the thread manipulates the money object.

The client 1

# client 1 127.0.0.1:6379> set money 100 OK 127.0.0.1:6379> set out 20 OK 127.0.0.1:6379> watch money 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> decrby money 20 QUEUED 127.0.0.1:6379(TX)> incrby out 20 QUEUED #Copy the code

Client 2 modifies the money monitored by client 1

# client 2 127.0.0.1:6379> get money "100" 127.0.0.1:6379> get out "20" 127.0.0.1:6379> set money 120 OK 127.0.0.1:6379> get money "120"Copy the code

Now let’s see what happens when client 1 performs a transaction.

127.0.0.1:6379(TX)> exec (nil) #redis is listening for another client 2 to change the value of money, so the transaction failsCopy the code

As can be seen from the above execution result, client 1 submits the transaction and finds that the monitored Money object has been modified, so the transaction execution fails at this time. At this time, we can use the Unwatch command to cancel the monitoring of the money object, and then use the Watch command to re-monitor the object to obtain the latest value. Then run -20 as follows:

127.0.0.1:6379> unwatch # select * from 'unwatch' where transaction execution fails Get the latest value OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> decrby money 20 QUEUED 127.0.0.1:6379(TX)> incrby out 20 QUEUED 1) (integer) 100 2) (integer) 40Copy the code

Errors in transactions

Compiled exception

Compilation exception indicates that the command syntax in the transaction queue is incorrect and cannot be compiled, that is, the error occurs when the command is executed. In this case, all commands in the transaction queue will not be executed. The following is an example:

127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set key1 v1 QUEUED 127.0.0.1:6379(TX)> set key2 v2 QUEUED 127.0.0.1:6379(TX)> getSet key2 (error) ERR wrong number of arguments for 'getset' command 127.0.0.1:6379(TX)> exec (error) EXECABORT Transaction discarded because of previous errors.Copy the code
Runtime exception

If a runtime error exists in the transaction queue, that is, an error occurs after Exec execution, such as incrementing or dividing string data by 0, other commands can be executed normally when this command is executed, but the wrong command will throw an exception. The following is an example:

127.0.0.1:6379> set k1 "v1" OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> incr QUEUED 127.0.0.1:6379(TX)> set K2 v2 QUEUED 127.0.0.1:6379(TX)> set K3 v3 QUEUED 127.0.0.1:6379(TX)> get K3 QUEUED 127.0.0.1:6379(TX)> exec 1) (error) ERR value is not an integer or out of range # String cannot increment 2) OK 3) OK 4) "v3"Copy the code

🏁 the above is a brief introduction to Redis transactions, if there are any mistakes, please leave a comment, if you think this article is helpful to you, click a like 👍 😋😻 👍