[redis series] redis learning VI, redis transaction processing and monitoring transactions

[redis series] redis learning VI, redis transaction processing and monitoring transactions

Write in front

The transactions we have learned are atomic, but the execution of multiple instructions in redis transactions does not guarantee atomicity

Essence of redis transaction

It is a set of commands. All commands in a transaction will be serialized. In the process of transaction execution, the commands are executed in order. They have

  • disposable
  • Order
  • exclusiveness

redis transactions do not have the concept of isolation level

In redis transaction, the command is executed in this way

The command is placed in the transaction and is not executed immediately. It is executed only when the command is initiated and triggered by exec

redis is a single instruction that guarantees atomicity, but transactions do not guarantee atomicity

The process of executing a transaction is like this:

  • multi open transaction
  • Join the team with various orders
  • exec execute transaction

Open transaction

MULTI

Start a transaction

EXEC

Execute the instructions in the transaction

After the transaction is executed, if you need to use the transaction again, you need to start the transaction again

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)> set name xiaozhu
QUEUED
127.0.0.1:6379(TX)> set age 19
QUEUED
127.0.0.1:6379(TX)> set hobby paly
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) OK
4) OK
5) OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set city changsha
QUEUED
127.0.0.1:6379(TX)> get city
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) "changsha"

Abandon transaction

DISCARD

Discard recently opened transactions

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set name xiaozhu
QUEUED
127.0.0.1:6379(TX)> set age 10
QUEUED
127.0.0.1:6379(TX)> set city beijing
QUEUED
127.0.0.1:6379(TX)> DISCARD
OK
127.0.0.1:6379> get city
(nil)
127.0.0.1:6379> get name
(nil)

Transaction error

There are two types of transaction errors:

  • Compile type error
  • runtime error

Compile type error

The code is written in error and cannot be compiled. At this time, all the instructions written in the transaction fail to execute

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set name xiaozhu
QUEUED
127.0.0.1:6379(TX)> set age 10
QUEUED
127.0.0.1:6379(TX)> set hobby play
QUEUED
127.0.0.1:6379(TX)> set city changsha
QUEUED
127.0.0.1:6379(TX)> set dream xxx
QUEUED
127.0.0.1:6379(TX)> setget hahaha  # If the instruction does not exist and the compilation fails, an error will be reported directly
(error) ERR unknown command `setget`, with args beginning with: `hahaha`,
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get city
(nil)

In case of compilation error, all instructions in the transaction will not be executed

runtime error

When the program is running, there is a problem with a specified logic, which only affects the execution of this instruction, and this instruction will run out of exception, which will not affect the execution of other instructions in the transaction

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set name xiaozhu
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> get name
QUEUED
127.0.0.1:6379(TX)> INCR name  # The incr instruction is used correctly, except that the name is a string and cannot be executed when running
QUEUED
127.0.0.1:6379(TX)> set age 29
QUEUED
127.0.0.1:6379(TX)> set hobby play
QUEUED
127.0.0.1:6379(TX)> exec
1) "xiaozhu"
2) (error) ERR value is not an integer or out of range
3) OK
4) OK
127.0.0.1:6379> get hobby
"play"
127.0.0.1:6379> get name
"xiaozhu"

According to the above results, the usage of incr instruction is correct, but incr can only operate on numbers. name is a string and cannot be self incremented. Therefore, an error is reported when running, and the execution of other instructions will not be affected in the transaction

watch monitoring of redis

watch monitoring, we can talk about optimistic lock and pessimistic lock

Optimistic lock:

  • I'm optimistic that there will be no problem at any time, so I won't lock it. When updating the data, I will judge if the data changes during this period
  • Optimistic lock will obtain a basic data version first
  • When updating data, it will compare whether this version has changed. If it has changed, the update fails. If it has not changed, the data will be updated

Pessimistic lock:

  • Very pessimistic. Whenever you think something will go wrong, you should lock it

redis monitoring test

Lock with watch to simulate bank withdrawal

  • money account has 2000
  • The outer account has 500
  • money account to outer account 500
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set money 2000
OK
127.0.0.1:6379> set outer 500
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 500
QUEUED
127.0.0.1:6379(TX)> INCRBY outer 500
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 1500
2) (integer) 1000

Start testing and simulate multiple threads to operate

redis client 1

  • money account has 2000
  • The outer account has 500
  • The money account is given to the outer account 500, and the execution has not started yet
127.0.0.1:6379> set money 2000
OK
127.0.0.1:6379> set outer 500
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 500
QUEUED
127.0.0.1:6379(TX)> INCRBY outer 500
QUEUED

Before the transaction operation of client 1 starts, client 2 performs the following operations

127.0.0.1:6379> set money 10000
OK
127.0.0.1:6379> set money 10000
OK

At this time, execute the exec instruction of client 1

127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379> get money
"10000"

It is found that when client 1 executes exec, it is a nil, indicating that the change failed because watch monitors that money has changed, so the transaction execution failed

unwatch

It is found that the transaction execution failed. You need to use the command unwatch to release the monitoring

127.0.0.1:6379> UNWATCH
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 1000
QUEUED
127.0.0.1:6379(TX)> INCRBY outer 1000
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 9000
2) (integer) 1500

This is the operation of redis to realize optimistic lock. Generally, the use scenario will be put into the seckill system for application

reference material:

redis_doc

Welcome to like, follow and collect

My friends, your persistence and support are the motivation to improve the quality

Well, that's all for this time

Technology is open, and our mentality should be open. Embrace change, grow into the sun and strive to move forward.

I'm Nezha, the Little Devil boy. Welcome to praise and pay attention to the collection. See you next time~

Keywords: Redis

Added by thewabbit1 on Sat, 26 Feb 2022 16:22:44 +0200