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