Redis from entry to proficiency [Advanced] Redis transaction details


insert image description here

0. Preface

Redis transaction is a mechanism for packaging multiple commands together for execution, which can guarantee the atomicity of these commands, that is, either all execution succeeds or all execution fails. Redis transactions are implemented using optimistic locking, and the specific implementation principles are as follows:

  1. open transaction

When a client executes the MULTI command, Redis will mark the client as a transaction state. At this point, all commands sent by the client will be temporarily stored in a transaction queue instead of being executed immediately.

  1. Execute business

When the client executes the EXEC command, Redis will remove the client state from the transaction state, and execute all the commands in the transaction queue in sequence. During execution, Redis will execute all the commands in the transaction queue without interruption. If any error occurs during execution, Redis will return the error message to the client and roll back the transaction.

  1. rollback transaction

If an error occurs during the execution of a transaction, Redis returns an error message to the client and rolls back the transaction. The way to roll back the transaction is to undo all the write commands executed by the client before and restore to the state before the transaction started.

Redis transactions are not truly atomic because commands in the transaction queue are not locked during execution. If multiple clients execute transactions concurrently, and those transactions involve the same critical data, then there is a possibility of a data race condition, resulting in data inconsistency. Therefore, in practical applications, it is necessary to evaluate and select according to specific business needs.
Redis implements the transaction function through four commands MULTI, DISCARD, EXEC and WATCH. This chapter first discusses the general transactions realized by using the three commands MULTI, DISCARD and EXEC, and then discusses the implementation of transactions with WATCH.

1. Basic process of Redis transaction

A Redis transaction is a collection of commands that are executed as a whole. All commands in the transaction are either executed or not executed at all, which ensures the atomicity of the transaction. During the execution of the transaction, the commands sent by other clients will not be executed, which can ensure the isolation of the transaction.

1. Business details

1.1. Start a transaction

A transaction can be started with the MULTI command. This command switches the state of the client from non-transactional to transactional.
A transaction can be started using the MULTI command:

127.0.0.1:6379> MULTI
OK

1.2. Command enqueue

In the transaction state, all commands sent by the client will not be executed immediately, but will be put into a queue first, and all commands will be executed sequentially when the EXEC command is invoked.

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key1 value1
QUEUED
127.0.0.1:6379> INCR key2
QUEUED
127.0.0.1:6379> MGET key1 key2
QUEUED

image.png

1.3. Executing transactions

image.png

All commands in a transaction can be executed using the EXEC command. If any command in the transaction fails, the entire transaction will be rolled back.

127.0.0.1:6379> EXEC
1) OK
2) (integer) 1
3) 1) "value1"
   2) "1"

##1.4. Executing commands in transactional and non-transactional states

In the transaction state, all commands sent by the client will not be executed immediately, but will be put into the queue. In the non-transactional state, the command sent will be executed immediately.

127.0.0.1:6379> SET key1 value1
OK

##1.5. DISCARD, MULTI and WATCH commands in transaction state

  • DISCARD command: used to cancel the transaction and clear the transaction queue.
    MULTI command: used to start a transaction.
    WATCH command: Used to monitor one or more keys. If these keys are modified by other clients before the transaction is executed, the transaction will be rolled back.
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key1 value1
QUEUED
127.0.0.1:6379> DISCARD
OK
  • MULTI command: used to start a transaction.
127.0.0.1:6379> MULTI
OK
  • WATCH command: Used to monitor one or more keys. If these keys are modified by other clients before the transaction is executed, the transaction will be rolled back.
127.0.0.1:6379> WATCH key1
OK

1.6. Transactions with WATCH

A transaction with WATCH can guarantee that the monitored key will not be modified by other clients during the execution of the transaction. If any of the watched keys is modified by another client, the transaction will be rolled back. Between the WATCH command and the EXEC command, the client can send any number of commands to the watched key, which will be enqueued but not executed immediately.
image.png

127.0.0.1:6379> WATCH key1
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key1 value1
QUEUED
127.0.0.1:6379> EXEC
(nil)

1.7. Implementation of WATCH command

The WATCH command in Redis is implemented using optimistic locking. Before executing a transaction, Redis will record the values ​​of the monitored keys, and when the transaction is executed, Redis will check again whether the values ​​of these keys have changed. If changed, the transaction will be rolled back. .

1.8. Triggering of WATCH

When an EXEC command is executed, Redis checks all watched keys for changes. If there are no changes, the transaction continues. If there is a change, the transaction will be rolled back

1.9. ACID properties of transactions

Redis transactions have ACID properties, namely atomicity, consistency, isolation, and durability.

  • Atomicity: All commands in the transaction are either executed or not executed at all, so that the atomicity of the transaction can be guaranteed.
  • Consistency: Before and after the execution of the transaction, the data in the database should remain consistent, that is, the data state before and after the execution of the transaction should satisfy certain constraints.
  • Isolation: During the execution of the transaction, the commands sent by other clients will not be executed, which can ensure the isolation of the transaction.
  • Durability: After the transaction execution is completed, the data should be persisted to the disk, so as to ensure the durability of the transaction.

The following is an example of a transaction that includes a WATCH command:

127.0.0.1:6379> SET key1 10
OK
127.0.0.1:6379> SET key2 5
OK
127.0.0.1:6379> WATCH key1 key2
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECR key1
QUEUED
127.0.0.1:6379> INCR key2
QUEUED
127.0.0.1:6379> EXEC
(nil)

In this example, the values ​​of key1 and key2 are set first. Next, monitor key1 and key2 using the WATCH command. Then, start a transaction using the MULTI command to enqueue operations on key1 and key2. Before the EXEC command was executed, another client modified the value of key2, which caused the transaction to be rolled back.

It should be noted that Redis transactions are not true ACID transactions, because Redis transactions cannot guarantee isolation. During the execution of a transaction, commands sent by other clients will not be executed, but if these commands are for keys involved in queued transaction commands, they will still modify the values ​​of these keys, and these modifications may affect The execution result of the transaction. Therefore, when using Redis transactions, you need to pay attention to this
#2. Code practice
We use jedis and Spring Boot to implement redis transactions respectively

1. jedis

(1) The pom.xml file depends on:

<dependencies>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.6.0</version>
    </dependency>
</dependencies>

(2) Code example:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class JedisTransactionDemo {
    
    
    public static void main(String[] args) {
    
    
        Jedis jedis = new Jedis("localhost", 6379);
        Transaction transaction = jedis.multi(); // 开启事务
        try {
    
    
            transaction.set("name", "张三");
            transaction.set("age", "18");
            transaction.exec(); // 提交事务
        } catch (Exception e) {
    
    
            transaction.discard(); // 回滚事务
        } finally {
    
    
            jedis.close(); // 关闭连接
        }
    }
}
  1. Spring Boot implements redis transaction

(1) The pom.xml file depends on:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>

(2) application.properties placement:

# Redis 配置
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0

(3) Code example:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Component;

@Component
public class RedisTransactionDemo {
    
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void test() {
    
    
        redisTemplate.execute(new SessionCallback<Object>() {
    
    
            @Override
            public Object execute(RedisOperations ops) throws DataAccessException {
    
    
                ops.multi(); // 开启事务
                try {
    
    
                    ops.opsForValue().set("name", "张三");
                    ops.opsForValue().set("age", "18");
                    ops.exec(); // 提交事务
                } catch (Exception e) {
    
    
                    ops.discard(); // 回滚事务
                }
                return null;
            }
        });
    }
}

The above is a sample project of jedis and Spring Boot implementing redis transactions, which can be modified and adjusted according to actual needs.

2. Summary

2.1. In transactional and non-transactional states

  1. Regardless of whether it is in a transactional state or in a non-transactional state, Redis commands are executed by the same function, so they share many general settings of the server, such as AOF configuration, RDB configuration, and memory limit, etc.

  2. However, there is still a little difference between the execution of commands in a transaction and ordinary commands. The two most important points are:
    commands in a non-transactional state are executed in units of a single command, and the clients of the previous command and the next command are not necessarily is the same;

  3. The transaction state is to execute all commands in the transaction queue in units of one transaction: unless the current transaction is executed, the server will not interrupt the transaction, nor will it execute other commands from other clients.

  4. In the non-transactional state, the result of executing the command will be returned to the client immediately;
    while the transaction is to collect the results of all commands into the reply queue, and then return it to the client as the result of the EXEC command.

  5. DISCARD, MULTI, and WATCH commands in the transaction state
    In addition to EXEC, when the server is in the transaction state, the other three commands that the server executes directly without adding to the transaction queue are DISCARD, MULTI, and WATCH.
    The DISCARD command is used to cancel a transaction. It clears the entire transaction queue of the client, then adjusts the client from the transaction state to the non-transaction state, and finally returns the string OK to the client, indicating that the transaction has been cancelled.

  6. Redis transactions cannot be nested. When the client is already in a transaction state and the client sends MULTI to the server, the server simply sends an error to the client and continues to wait for other commands to enter the queue. The sending of the MULTI command will not cause the entire transaction to fail, nor will it modify the existing data in the transaction queue.

  7. WATCH can only be executed before the client enters the transaction state. Sending the WATCH command in the transaction state will cause an error, but it will not cause the entire transaction to fail, nor will it modify the existing data in the transaction queue (and the previous processing of MULTI same situation).

2.2. Summary

Redis transactions are a collection of commands with ACID properties of atomicity, consistency, isolation, and durability. All commands in the transaction are either all executed or not executed at all, which can guarantee the atomicity of the transaction. During the execution of the transaction, the commands sent by other clients will not be executed, which can ensure the isolation of the transaction. Before executing a transaction, you can use the WATCH command to monitor one or more keys. If these keys are modified by other clients before the transaction is executed, the transaction will be rolled back. The ACID nature of transactions can ensure data consistency and reliability.

2.3. Why Redis transactions are not truly atomic operations

After studying this chapter, we try to answer this question.
Redis transactions are not truly atomic operations, mainly for the following reasons:

  1. Redis transactions are implemented based on optimistic locking and will not lock any key data. During transaction execution, if other clients modify the same key data, the transaction may not succeed. In this case, Redis will rollback the entire transaction and return an error message. Therefore, Redis transactions cannot guarantee absolute atomicity like database transactions.

  2. Redis transactions do not lock commands in the transaction queue during execution, but monitor key data changes during execution. If key data changes during transaction execution, Redis will roll back the transaction and return an error message. However, if abnormal conditions such as network failure or client crash occur during transaction execution, Redis cannot roll back the transaction, which may lead to data inconsistency.

Although Redis transactions are not real atomic operations, for most application scenarios, Redis transactions are sufficient to meet business needs. It should be noted that when using Redis transactions, attention should be paid to the correctness and reliability of transactions to avoid data inconsistencies.

2.4. Why Redis cannot automatically roll back transactions in abnormal situations such as client crashes

  1. Abnormal conditions such as client crashes may interrupt the execution of Redis transactions, making it impossible to roll back transactions automatically. Specifically, when the client executes the MULTI command to start a transaction, all commands are not executed immediately, but are temporarily stored in a transaction queue. When the client executes the EXEC command to submit the transaction, Redis will execute all the commands in the transaction queue in sequence.
  2. If abnormal conditions such as network failure or client crash occur during transaction execution, Redis cannot automatically commit the transaction, so it cannot automatically roll back the transaction. In this case, it is necessary to manually execute the corresponding command to cancel the command that has been executed, so as to realize the rollback of the transaction. Specifically, you can use the DISCARD command to undo all commands in a transaction that have not been executed, or the converse to undo commands that have already been executed.

3. Redis from entry to proficiency series of articles

"Redis from entry to proficiency [advanced chapter] detailed explanation of the object mechanism" "
Redis from entry to proficiency [advanced chapter] detailed explanation of the message delivery publishing subscription model"
"Redis from entry to proficiency [advanced chapter] persistent AOF Detailed Explanation"
"Redis from entry to proficiency [advanced chapter]: detailed explanation of persistent RDB" "
Redis from entry to proficiency [advanced chapter] detailed explanation of the underlying data structure dictionary (Dictionary)" "
Redis from entry to proficiency [advanced chapter] ] Detailed explanation of the underlying data structure QuickList "
"Redis from entry to proficiency [advanced articles]: detailed explanation of the underlying data structure Simple Dynamic String (SDS)" "
Redis from entry to proficiency [advanced articles] compression of the underlying data structure List (ZipList) Detailed Explanation"
"Redis from entry to proficiency [Advanced Chapter]: detailed explanation and usage examples of the data type Stream"
insert image description here
Hello everyone, I am Freezing Point, today's Redis from entry to proficiency [Advanced Chapter] Redis transaction detailed explanation, That's all there is to it. If you have questions or opinions, you can leave a message in the comment area.

Guess you like

Origin blog.csdn.net/wangshuai6707/article/details/131610401