Redis and redis Design and Implementation
Redis transactions are based on four commands:
Create a transaction
Redis transaction fromMULTIWhen the command starts, MULTI always returns "OK ".
Then you can start to input operation data. Each operation command enters the queue.
Last executedEXECTo run the command in the queue.
For example:
> MULTIOK> INCR fooQUEUED> INCR barQUEUED> EXEC1) (integer) 12) (integer) 1
What if an error occurs in the transaction?
First, we divide the errors in the transaction into two types:
- An error was found before entering the queue, such as a command syntax error.
- An error is found after EXEC is executed. For example, two operations of different data types are performed on the same key.
The first one is easy to understand, as in the example above, "QUEUED" is immediately returned after the queue is successfully entered ".
If the Transaction fails to enter the queue, the entire Transaction will become invalid, prompting "Transaction ".DiscardedBecause of previous errors ."
Any error that occurs after EXEC is executed will be executed if it enters the queue successfully,Even if a command fails to be executed in the same thing, other commands will be executed..
This surprised those who used relational databases,Why does Redis not support roll back??
Two points on the official website:
Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.
Redis is internally simplified and faster because it does not need the ability to roll back.
Some people say that not supporting roll back will lead to various bugs. But it should be clear that roll back is not used to solve programming errors.
In addition, there are only two possible causes of Command failure:
- Syntax Error
- The operation does not match the data type of the key.
Given this, roll back makes almost no sense. Redis prefers not to support roll back, but to maintain simplicity and efficiency.
Discard transactions
DISCARDIt can be used to discard the current transaction and restore the connection status to normal.
The usage is as follows:
> SET foo 1OK> MULTIOK> INCR fooQUEUED> DISCARDOK> GET foo"1"
Atomicity
Check-and-set(CAS) and other operations often have final state conditions.
Redis providesWATCHUsed to observe key changes.
When an observed key changes before EXEC execution, the entire transaction will terminate and return Nil, and the observation of the key will also end.
When I first came into contact with WATCH, I felt this kind of processing method was obscure. Can't I add a display lock or something?
Fortunately, the official website provides a full explanation. Assume that Redis does not provide INCR. Now we need to simulate an incremental operation:
val = GET mykeyval = val + 1SET mykey $val
There is no problem when a client performs this operation, but when multiple clients perform this operation together, the actual state conditions will appear.
For example, the client A and client B both GET mykey and GET 10. Therefore, the result of the two executions is 11 instead of 12.
After adding WATCH:
WATCH mykeyval = GET mykeyval = val + 1MULTISET mykey $valEXEC
If something else between WATCH and EXEC changes the observed key, the transaction will fail.
If you want the transaction to be successfully executed, You need to execute it in the loop. Of course, this is also a locking method.
As a matter of fact, it is not common for multiple clients to access the same key. Let's take a look at the specific situation.
Correspondingly, an UNWATCH can be used to release all the observed keys.
For example, in the following example, the INCR in the transaction is successfully executed:
WATCH keyUNWATCH keyMULTIINCR keyEXEC
Note the following for WATCH:EXPIRE)The key will not be changed by WATCH because it expires.