Redis series of directories

Redis series – distributed lock

Redis series – Cache penetration, cache breakdown, cache avalanche

Why Is Redis so fast?

Redis series — Data Persistence (RDB and AOF)

Redis series – consistent hash algorithm

Redis series – High Availability (Master slave, Sentinel, Cluster)

Redis series – Things and Optimism lock

Redis series — Geospatial: Do you have Lao Wang next door?

Bitmaps: Did you check in today?

What is a Bloom filter?!

When learning mysql, we always say mysql has things, things have ACID, Atomicity, Consistency, Isolation, Durability.

Is there anything in Redis? How does that work? Let’s use the actual test to tell you the results.

Objects (multi/exec /discard)

In Redis, there are things. But redis things are weak things. There is no isolation level for a thing, and multiple commands in a thing are not atomic. For these reasons, redis is rarely used in actual production.

Redis: A set of commands. All commands in the transaction are serialized and placed in a queue, and the commands are executed sequentially as the transaction executes.

Redis single command guarantees atomicity, multiple commands do not.

1. Implementation of normal things

There are three steps to redis:

  • Open things (Multi)

  • Command queuing (The commands to be executed are written to the queue. The queue is a group of commands.)

  • Executive (exec)

Display of normal things:

127.0.0.1:6379>
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> multi  # Turn things onOK 127.0.0.1:6379 >set name wuxl  Enter the queueQUEUED 127.0.0.1:6379 >set age 30    Enter the queueQUEUED 127.0.0.1:6379 > get the nameEnter the queueQUEUED 127.0.0.1:6379 >set addr shanghai  Enter the queueQUEUED 127.0.0.1:6379 >exec    # Implement things
1) OK
2) OK
3) "wuxl"4) OK 127.0.0.1:6379 >Copy the code

After the above items are submitted, four commands will be executed in sequence, and the items will exit after completion of execution.

Cancel things

After an item is opened, it can also be discarded:

127.0.0.1:6379>
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> setThe name wuxl QUEUED 127.0.0.1:6379 >setAge 30 QUEUED 127.0.0.1:6379> discard# Cancel thingsOK 127.0.0.1:6379 > get the ageThe command in the transaction was not executed(nil) 127.0.0.1:6379 >Copy the code

3. Things go wrong

Compile error

Compile error, because the command in the queue itself has a problem, resulting in the command queue error. If there is a compilation error, executing exec will indicate failure, and all commands cannot be executed.

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> setName wuxl QUEUED 127.0.0.1:6379> get# error command, join queue error
(error) ERR wrong number of arguments for 'get' command127.0.0.1:6379 >setThe age of 30 QUEUED 127.0.0.1:6379 >exec           Error: all commands cannot be executed
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get name       No result is found
(nil)
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379>
Copy the code

Runtime error

A runtime error is a command that is pushed and has no errors, but reports an error when it is executed out of queue, such as the following for incrementing a String.

127.0.0.1:6379 > flushall OK 127.0.0.1:6379 >set name wuxl        # initialize name, which is string
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> setAge 30 QUEUED 127.0.0.1:6379> INCr nameSelect * from 'team' where name = 'team'; The command itself is fine, but an error occurs when it is executedQUEUED 127.0.0.1:6379 >setAddr Shanghai QUEUED 127.0.0.1:6379 >exec                 Execute each command in turn
1) OK
2) (error) ERR value is not an integer or out of range   The second command failed
3) OK
127.0.0.1:6379> get name                                 
"wuxl"127.0.0.1:6379 > get the ageAll other commands are executed successfully
"30"127.0.0.1:6379 > get addr"shanghai"127.0.0.1:6379 >Copy the code

As you can see, an error is reported, but the object is not rolled back, and the error does not affect subsequent command execution, only the execution of the error command will fail. So, for commands in queues, there is no atomicity.

Optimistic locking (watch)

1. Optimistic and pessimistic locks

Pessimistic locking

Think that the possibility of concurrency problems is relatively large, relatively pessimistic. This is where real locking is required. Locking degrades performance.

Optimistic locking

Think the possibility of concurrency problem is relatively small, more optimistic. In this case, you do not need to lock the data. You only need to compare whether the original data has changed during the modification operation. If there is no change, modify the data. The version field is typically used in mysl.

Redis provides the watch command to monitor whether the data has been modified by other threads. If the data has been modified, the modification fails; if the data has not been modified, the modification succeeds. The watch command can be seen as an implementation of Redis’s optimistic locking.

2. Transfer simulation

Below, the simulated scenario is a transaction between two accounts.

Single thread simulation

Normal transfer process:

127.0.0.1:6379 > flushall# delete databaseOK 127.0.0.1:6379 >set acc1 1000 The paid account has 1000 yuanOK 127.0.0.1:6379 >set acc2 0     I have 0 yuan in my collected accountOK 127.0.0.1:6379 > multi# Turn things on
OK
127.0.0.1:6379> decrby acc1 100 Deduct 100 from paid account
QUEUED
127.0.0.1:6379> incrby acc2 100 # Collect account receive 100QUEUED 127.0.0.1:6379 >exec            # Implement things(1)integer), 900 (2)integer) 100
127.0.0.1:6379> get acc1         The paid account now has 900
"900"127.0.0.1:6379 > get acc1acc2The collected account now has 100
"100"127.0.0.1:6379 >Copy the code

After the single thread simulated transfer above, the paying account now has 900 after the payment, and the receiving account now has 100. It’s a normal process.

Concurrent simulation

In this process, if before the execution of exec, someone wants to acc1 charged 1000 yuan, this time there will be a concurrency problem, if you do not use the lock, after the execution of exec, the result will be what? Acc1 has 1900, acc1 has 100, which is also correct. Why? Because things in Redis are not isolated, the two things affect each other.

If it is necessary to compare whether ACC1 has changed during exec execution, if it has changed, the transfer will fail. How to deal with this, this can use Redis watch to do optimistic lock. The following simulates a situation where two clients modify redis data at the same time and use Watch to do optimistic locking.

Step 1: Initialize the amounts for both accounts. Acc1 is the paying account, acc2 is the receiving account.

127.0.0.1:6379 > flushall OK 127.0.0.1:6379 >set acc1 1000   # Pay accountOK 127.0.0.1:6379 >set acc2 0      # Collect accountOK 127.0.0.1:6379 >Copy the code

Step 2: Use client I, open watch to monitor whether ACC1 changes, open things at the same time, order to join the team (transfer 100 yuan), do not execute things at first.

127.0.0.1:6379 > 127.0.0.1:6379 > watch acc1# Use watch to monitor acc1's account to see if it changes when executing thingsOK 127.0.0.1:6379 > multi# Turn things on
OK
127.0.0.1:6379> decrby acc1 100   # Simulate payment
QUEUED
127.0.0.1:6379> incrby acc2 100   # Simulate collecting moneyQUEUED 127.0.0.1:6379 >Copy the code

Step 3: Use client 2 to change the amount of acc1 account.

127.0.0.1:6379>
127.0.0.1:6379> incrby acc1 1000 Add another 1000 to acc1's account
(integer) 2000
127.0.0.1:6379> get acc1         # This is the change in acc1's account, with 2000
"2000"127.0.0.1:6379 >Copy the code

As you can see, client 2 execution succeeded!! If it’s mysql, client 2 should be blocked at this point and must wait for client 1 to complete. This is also the above mentioned redis things are not isolated, will affect each other.

Step 4: Using client 1, execute things.

127.0.0.1:6379 >exec            If acc1 changes, it will fail to execute. If ACC1 does not change, the execution succeeds
(nil) # failed to execute127.0.0.1:6379 > get acc1"2000"127.0.0.1:6379 > get acc1acc2"0"127.0.0.1:6379 >Copy the code

It can be seen that client 2 modified the amount of acc2’s account. Before client 1 executed exec, Watch monitored the change of acc1’s amount, so the transfer process of client 1 failed. This is actually using Watch to implement an optimistic lock.

Done, done!

[spread knowledge, share value], thank small partners attention and support, I am [Zhuge small ape], a hesitation in the struggle of the Internet migrant workers!!