[redis series] redis learning VI, redis transaction processing and monitoring transactions
Write in front
The transactions we have learned are atomic, but the execution of multiple instructions in redis transactions does not guarantee atomicity
Essence of redis transaction
It is a set of commands. All commands in a transaction will be serialized. In the process of transaction execution, the commands are executed in order. They have
- disposable
- Order
- exclusiveness
redis transactions do not have the concept of isolation level
In redis transaction, the command is executed in this way
The command is placed in the transaction and is not executed immediately. It is executed only when the command is initiated and triggered by exec
redis is a single instruction that guarantees atomicity, but transactions do not guarantee atomicity
The process of executing a transaction is like this:
- multi open transaction
- Join the team with various orders
- exec execute transaction
Open transaction
MULTI
Start a transaction
EXEC
Execute the instructions in the transaction
After the transaction is executed, if you need to use the transaction again, you need to start the transaction again
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)> set name xiaozhu QUEUED 127.0.0.1:6379(TX)> set age 19 QUEUED 127.0.0.1:6379(TX)> set hobby paly QUEUED 127.0.0.1:6379(TX)> exec 1) OK 2) OK 3) OK 4) OK 5) OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379(TX)> set city changsha QUEUED 127.0.0.1:6379(TX)> get city QUEUED 127.0.0.1:6379(TX)> exec 1) OK 2) "changsha"
Abandon transaction
DISCARD
Discard recently opened transactions
127.0.0.1:6379> flushdb OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379(TX)> set name xiaozhu QUEUED 127.0.0.1:6379(TX)> set age 10 QUEUED 127.0.0.1:6379(TX)> set city beijing QUEUED 127.0.0.1:6379(TX)> DISCARD OK 127.0.0.1:6379> get city (nil) 127.0.0.1:6379> get name (nil)
Transaction error
There are two types of transaction errors:
- Compile type error
- runtime error
Compile type error
The code is written in error and cannot be compiled. At this time, all the instructions written in the transaction fail to execute
127.0.0.1:6379> flushdb OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set name xiaozhu QUEUED 127.0.0.1:6379(TX)> set age 10 QUEUED 127.0.0.1:6379(TX)> set hobby play QUEUED 127.0.0.1:6379(TX)> set city changsha QUEUED 127.0.0.1:6379(TX)> set dream xxx QUEUED 127.0.0.1:6379(TX)> setget hahaha # If the instruction does not exist and the compilation fails, an error will be reported directly (error) ERR unknown command `setget`, with args beginning with: `hahaha`, 127.0.0.1:6379(TX)> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get city (nil)
In case of compilation error, all instructions in the transaction will not be executed
runtime error
When the program is running, there is a problem with a specified logic, which only affects the execution of this instruction, and this instruction will run out of exception, which will not affect the execution of other instructions in the transaction
127.0.0.1:6379> flushdb OK 127.0.0.1:6379> set name xiaozhu OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> get name QUEUED 127.0.0.1:6379(TX)> INCR name # The incr instruction is used correctly, except that the name is a string and cannot be executed when running QUEUED 127.0.0.1:6379(TX)> set age 29 QUEUED 127.0.0.1:6379(TX)> set hobby play QUEUED 127.0.0.1:6379(TX)> exec 1) "xiaozhu" 2) (error) ERR value is not an integer or out of range 3) OK 4) OK 127.0.0.1:6379> get hobby "play" 127.0.0.1:6379> get name "xiaozhu"
According to the above results, the usage of incr instruction is correct, but incr can only operate on numbers. name is a string and cannot be self incremented. Therefore, an error is reported when running, and the execution of other instructions will not be affected in the transaction
watch monitoring of redis
watch monitoring, we can talk about optimistic lock and pessimistic lock
Optimistic lock:
- I'm optimistic that there will be no problem at any time, so I won't lock it. When updating the data, I will judge if the data changes during this period
- Optimistic lock will obtain a basic data version first
- When updating data, it will compare whether this version has changed. If it has changed, the update fails. If it has not changed, the data will be updated
Pessimistic lock:
- Very pessimistic. Whenever you think something will go wrong, you should lock it
redis monitoring test
Lock with watch to simulate bank withdrawal
- money account has 2000
- The outer account has 500
- money account to outer account 500
127.0.0.1:6379> flushall OK 127.0.0.1:6379> set money 2000 OK 127.0.0.1:6379> set outer 500 OK 127.0.0.1:6379> watch money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> DECRBY money 500 QUEUED 127.0.0.1:6379(TX)> INCRBY outer 500 QUEUED 127.0.0.1:6379(TX)> exec 1) (integer) 1500 2) (integer) 1000
Start testing and simulate multiple threads to operate
redis client 1
- money account has 2000
- The outer account has 500
- The money account is given to the outer account 500, and the execution has not started yet
127.0.0.1:6379> set money 2000 OK 127.0.0.1:6379> set outer 500 OK 127.0.0.1:6379> watch money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> DECRBY money 500 QUEUED 127.0.0.1:6379(TX)> INCRBY outer 500 QUEUED
Before the transaction operation of client 1 starts, client 2 performs the following operations
127.0.0.1:6379> set money 10000 OK 127.0.0.1:6379> set money 10000 OK
At this time, execute the exec instruction of client 1
127.0.0.1:6379(TX)> exec (nil) 127.0.0.1:6379> get money "10000"
It is found that when client 1 executes exec, it is a nil, indicating that the change failed because watch monitors that money has changed, so the transaction execution failed
unwatch
It is found that the transaction execution failed. You need to use the command unwatch to release the monitoring
127.0.0.1:6379> UNWATCH OK 127.0.0.1:6379> watch money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> DECRBY money 1000 QUEUED 127.0.0.1:6379(TX)> INCRBY outer 1000 QUEUED 127.0.0.1:6379(TX)> exec 1) (integer) 9000 2) (integer) 1500
This is the operation of redis to realize optimistic lock. Generally, the use scenario will be put into the seckill system for application
reference material:
Welcome to like, follow and collect
My friends, your persistence and support are the motivation to improve the quality
Well, that's all for this time
Technology is open, and our mentality should be open. Embrace change, grow into the sun and strive to move forward.
I'm Nezha, the Little Devil boy. Welcome to praise and pay attention to the collection. See you next time~