preface
-
affair
① atomicity. A transaction is an inseparable work unit, and the operations included in the transaction are either done or not done.
② Consistency. Transactions must change the database from one consistency state to another. Consistency and atomicity are closely related.
③ isolation. The execution of a transaction cannot be interfered by other transactions. That is, the operations and data used within a transaction are isolated from other concurrent transactions, and the concurrent transactions cannot interfere with each other.
④ durability. Persistence, also known as permanence, means that once a transaction is committed, its changes to the data in the database should be permanent. The following other operations or faults should not have any impact on it.
There is no concept of isolation level in Redis transactions!
In Redis, a single command guarantees atomicity, but transactions do not guarantee atomicity!
-
Optimistic lock
① When concurrency may occur in the program, it is necessary to ensure the accuracy of the data in the case of concurrency, so as to ensure that when the current user operates with other users, the result is the same as that when he operates alone.
② If concurrency control is not done well, dirty reading, unreal reading and non repeatable reading may be caused.
Optimistic locking can be realized in Redis!
1, How does Redis implement transactions?
① Normal execution of transactions
127.0.0.1:6379> multi #Open transaction OK 127.0.0.1:6379> set name dingyongjun #Add data QUEUED 127.0.0.1:6379> set age 26 #Add data QUEUED 127.0.0.1:6379> set high 172 #Add data QUEUED 127.0.0.1:6379> exec Execute transactions 1) OK 2) OK 3) OK 127.0.0.1:6379> get name #Successful data acquisition proves successful transaction execution "dingyongjun" 127.0.0.1:6379> get age "26"
② Abandon transaction
127.0.0.1:6379> multi #Open transaction OK 127.0.0.1:6379> set name dingyongjun #Add data QUEUED 127.0.0.1:6379> set age 26 #Add data QUEUED 127.0.0.1:6379> discard #Abandon transaction OK 127.0.0.1:6379> get name #Will not perform the add operation in the transaction (nil)
③ Compile time exceptions, code problems, or command problems, all commands will not be executed
127.0.0.1:6379> multi #Open transaction OK 127.0.0.1:6379> set name dingyongjun #Add data QUEUED 127.0.0.1:6379> set age 23 #Add data QUEUED 127.0.0.1:6379> getset name #Enter an incorrect command, and an error has been reported at this time, but this is still in the transaction queue (error) ERR wrong number of arguments for 'getset' command 127.0.0.1:6379> set high 173 #Add data QUEUED 127.0.0.1:6379> exec #Execute transactions, report errors, and all commands will not be executed (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get name #The obtained data is empty, which proves that it has not been implemented (nil)
④ For runtime exceptions, except that syntax errors will not be executed and exceptions are thrown, other correct commands can be executed normally
127.0.0.1:6379> multi #Open transaction OK 127.0.0.1:6379> set name dingyongjun #Add string data QUEUED 127.0.0.1:6379> incr name #Self incrementing string data QUEUED 127.0.0.1:6379> set age 23 #Add data QUEUED 127.0.0.1:6379> get age #get data QUEUED 127.0.0.1:6379> exec #Execute transactions. Although an error is reported in the auto increment operation of string data, other commands can be executed normally 1) OK 2) (error) ERR value is not an integer or out of range 3) OK 4) "23" 127.0.0.1:6379> get age #Data acquisition succeeded "23"
⑤ Summary: it can be concluded from the above that Redis supports single command transactions, but transactions cannot guarantee atomicity!
2, How does Redis implement optimistic lock?
① watch
127.0.0.1:6379> set money 100 #Add money 100 OK 127.0.0.1:6379> set cost 0 #Add expense 0 OK 127.0.0.1:6379> watch money #Monitor money OK 127.0.0.1:6379> multi #Open transaction OK 127.0.0.1:6379> DECRBY money 30 #Money -30 QUEUED 127.0.0.1:6379> incrby cost 30 #Cost +30 QUEUED 127.0.0.1:6379> exec #Execute transaction, successful! Only when there is no change in the data can we succeed 1) (integer) 70 2) (integer) 30
② Multithreaded test watch
#Thread 1
#Thread 1 127.0.0.1:6379> set money 100 #Add money 100 OK 127.0.0.1:6379> set cost 0 #Add expense 0 OK 127.0.0.1:6379> watch money #Turn on monitoring (Le Guan lock) OK 127.0.0.1:6379> multi #Open transaction OK 127.0.0.1:6379> DECRBY money 20 #Money -20 QUEUED 127.0.0.1:6379> INCRBY cost 20 #Cost +20 QUEUED #Don't execute it here. Execute thread 2 first to modify the monitored value 127.0.0.1:6379> exec #An error is reported during execution, because we have monitored the value of money. If the transaction wants to operate on this value #The monitor will judge whether this value is normal. If it changes, the transaction execution fails! (nil)
#Thread 2
#Thread 2, this operation is executed before the transaction is executed 127.0.0.1:6379> INCRBY money 20 #Money +20 (integer) 120
③ Summary: the difference between optimistic lock and pessimistic lock.
Pessimistic lock: there will be problems at any time, so I have been monitoring. Before the current step is completed, no thread is allowed to execute, which is a waste of performance! Generally not used!
Optimistic lock: only when updating the data, judge whether someone has modified the monitored data during this period. If not, the transaction will be executed normally, otherwise the execution will fail!