Redis basic transaction operations

Posted by Kodak07 on Sat, 22 Jan 2022 08:03:23 +0100

Most of the notes are taken when station B meets Redis said by crazy God. By the way, the pictures and texts are combined and recorded for easy review and only for learning!
Video address: https://www.bilibili.com/video/BV1S54y1R7SB?t=250 The author is really very good. I remember Sanlian
If there is infringement, please contact to delete!

1. Description

A single redis command is atomic, but a redis transaction cannot be atomic;

Redis transaction essence: a collection of commands.
-----------------Queue set execution-------------------

Each command in the transaction will be serialized. It will be executed in order during execution, and other commands are not allowed to interfere.

  • disposable
  • Order
  • exclusiveness

Redis transactions do not have the concept of isolation level
Redis single command guarantees atomicity, but transactions do not guarantee atomicity!

2. Redis transaction operation process

Open transaction (multi)
Command to join the queue (perform various operations...)
Execute transaction (exec)

Therefore, the commands in the transaction are not executed at the time of joining, and will not be executed until commit (Exec) is completed at one time.

127.0.0.1:6379> multi # Open transaction
OK
127.0.0.1:6379(TX)> set k1 v1 # Order to join the team
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k1
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec # Execute transaction
1) OK
2) OK
3) "v1"
4) OK

Cancel transaction (occurred)

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> DISCARD # Abandon transaction
OK
127.0.0.1:6379> EXEC 
(error) ERR EXEC without MULTI # Transaction is not currently open
127.0.0.1:6379> get k1 # The command in the abandoned transaction was not executed
(nil)

3. Transaction error

Compile type error: code syntax error (compile time exception). All commands will not be executed

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> getset k1  # This is a syntax error command
(error) ERR wrong number of arguments for 'getset' command  # An error will be reported, but it will not affect the subsequent order to join the team 
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors. # Execution error
127.0.0.1:6379> get k1
(nil)# Other commands were not executed

Runtime error: code logic error (runtime exception) * * other commands can be executed normally * * > >, so transaction atomicity is not guaranteed

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> INCR k1 # This command has a logical error (incrementing the string)
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range # Error reporting during operation
4) "v2" # Other commands are executed normally

# Although an error is reported in one of the commands, the subsequent instructions are still executed normally and successfully.
# Therefore, a single Redis instruction guarantees atomicity, but Redis transactions cannot guarantee atomicity.

4. Monitoring

Pessimistic lock:

  • I am very pessimistic. I think there will be problems at any time, and I will lock whatever I do

Optimistic lock:

  • I'm optimistic that there will be no problem at any time, so I won't lock it! When updating the data, judge whether anyone has modified the data during this period
    Get version
  • Compare version when updating

Using the watch key to monitor the specified data is equivalent to optimistic locking.

Normal execution

127.0.0.1:6379> set money 100 # Set balance: 100
OK
127.0.0.1:6379> set out 0 # Expenditure usage: 0
OK
127.0.0.1:6379> watch money # Monitor money (lock)
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> DECRBY money 20
QUEUED
127.0.0.1:6379> INCRBY out 20
QUEUED
127.0.0.1:6379> exec # The monitoring value has not been modified halfway, and the transaction is executed normally
1) (integer) 80
2) (integer) 20

Test multithreading to modify the value. Use watch as an optimistic lock operation of redis (equivalent to getversion)
We start another client to simulate queue jumping thread.
Thread 1:

127.0.0.1:6379> watch money # money lock
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> DECRBY money 10
QUEUED
127.0.0.1:6379> INCRBY out 10
QUEUED
127.0.0.1:6379> 	# The transaction is not executed at this time

Thread 2:

127.0.0.1:6379> set money 1000 # Reset amount: 1000
OK

Return to thread 1 and execute the transaction:

127.0.0.1:6379> EXEC # Before execution, another thread modifies our value, which will lead to transaction execution failure
(nil) # If there is no result, the transaction execution fails

127.0.0.1:6379> get money # Thread 2 modification takes effect
"600"
127.0.0.1:6379> get out # Thread 1 transaction execution failed. The value has not been modified
"0"

Unlock to get the latest value, and then lock for transaction.

Unlock with unwatch.

Note: the lock will be automatically released every time exec is submitted, regardless of whether it is successful or not

Topics: Redis