This is the fifth day of my participation in the More text Challenge. For details, see more text Challenge

This article is participating in the “Java Theme Month – Java Development in action”. See the link to the event for more details


Related articles

Redis combat summary: Redis combat


preface

  • The transaction

(1) Atomicity. A transaction is an indivisible unit of work that includes either all or none of the operations.

(2) Consistency. Transactions must change the database from one consistent state to another. Consistency is closely related to atomicity.

(3) Isolation. The execution of one transaction cannot be interfered with 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.

4. They look beautiful. Persistence, also known as permanence, means that once a transaction is committed, its changes to the data in the database should be permanent. Subsequent operations or failures should not have any impact on it.

Transactions in Redis have no noIsolation levelThe concept of!

The Redis single imperative guaranteeatomicYes, but transactions are not guaranteedatomic!

  • Optimistic locking

(1) When there may be concurrent situations in the program, it is necessary to ensure the accuracy of the data in the concurrent situation, so as to ensure that the results obtained by the current user and other users operating together are the same as the results obtained when he operates alone.

(2) Improper concurrency control may lead to dirty reads, phantom reads, and non-repeatable reads.

This is possible in RedisOptimistic locking!!!!

How does Redis implement transactions?

① Execute the transaction normally

127.0.0.1:6379 > multi# Open transactionOK 127.0.0.1:6379 >set name dingyongjun  # Add dataQUEUED 127.0.0.1:6379 >set age 26  # Add dataQUEUED 127.0.0.1:6379 >set high 172  # Add dataQUEUED 127.0.0.1:6379 >execExecute transaction 1) OK 2) OK 3) OK 127.0.0.1:6379> get nameTransaction execution is successful if data is obtained successfully
"dingyongjun"127.0.0.1:6379 > get the age"26"
Copy the code

② Discard transaction

127.0.0.1:6379 > multi# Open transactionOK 127.0.0.1:6379 >set name dingyongjun  # Add dataQUEUED 127.0.0.1:6379 >set age 26  # Add dataQUEUED 127.0.0.1:6379 > the discard# Discard transactionOK 127.0.0.1:6379 > get the name# Will not perform the add operation within the transaction
(nil)
Copy the code

(3) All commands will not be executed if there is a compile-time exception, code problem, or command problem

127.0.0.1:6379 > multi# Open transactionOK 127.0.0.1:6379 >set name dingyongjun  # Add dataQUEUED 127.0.0.1:6379 >set age 23  # Add dataQUEUED 127.0.0.1:6379 > getset name# Enter an incorrect command, but it is still queued
(error) ERR wrong number of arguments for 'getset' command127.0.0.1:6379 >set high 173  # Add dataQUEUED 127.0.0.1:6379 >exec  < span style = "word-break: inherit
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get name  # Obtain data is empty, indicating no execution
(nil)
Copy the code

(4) Runtime exceptions, except syntax errors will not be executed and after exceptions are thrown, other correct commands can be executed normally

127.0.0.1:6379 > multi# Open transactionOK 127.0.0.1:6379 >set name dingyongjun  # Add string dataQUEUED 127.0.0.1:6379 > incr name# Increment string dataQUEUED 127.0.0.1:6379 >set age 23  # Add dataQUEUED 127.0.0.1:6379 > get the age# Retrieve dataQUEUED 127.0.0.1:6379 >exec  # Execute transaction. Although the string data increment operation reported an error, but the other commands are fine
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "23"127.0.0.1:6379 > get the age# Data obtained successfully
"23"
Copy the code

⑤ Conclusion: Redis supports single command transactions, but transactions do not guarantee atomicity!

How does Redis implement optimistic locking?

① Watch over

127.0.0.1:6379 >set money 100  # Add money 100OK 127.0.0.1:6379 >set cost 0  # Add cost 0OK 127.0.0.1:6379 > watch money# Monitor moneyOK 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  Spend + 30 #QUEUED 127.0.0.1:6379 >exec  # Execute transaction, success! This time the data has not changed to be successful(1)integer), 70 (2)integer) 30
Copy the code

Watch # thread 1

Thread # 1127.0.0.1:6379 >set money 100  # Add money 100OK 127.0.0.1:6379 >set cost 0  # Add cost 0OK 127.0.0.1:6379 > watch money# Enable monitoring (optimistic 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   Spend + 20 #
QUEUED
# Do not execute here, first execute thread 2 to change the monitored value127.0.0.1:6379 >exec  # Execution error because we monitor the value of money if the transaction wants to operate on this value before
The monitor will determine if this value is normal, if it changes, the transaction will fail!
(nil)
Copy the code

Thread # 2

# thread 2, this operation executes before the transaction executes127.0.0.1:6379 > INCRBY money 20# money + 20
(integer) 120
Copy the code

③ Conclusion: optimistic lock and pessimistic lock difference. Pessimistic locking: it’s always a problem, so it’s a waste of performance to keep monitoring and not let any threads execute until the current step is complete! Generally not used! Optimistic locking: only when the data is updated to determine whether someone has modified the monitored data during this period, if not, the transaction will be executed normally, otherwise the execution will fail!


There is still a long way to go, but I will continue to search for more and more. So much for Redis’ affairs and optimistic locks, if you think I blogger has done a good job! Writing is not easy, please like, follow, comment to give the blogger a encouragement ~