Using redis transaction in SpringBoot

Posted by pmcconaghy on Wed, 09 Mar 2022 13:21:01 +0100

This article is based on springboot 2 X
Transactions are often used in the development of relational databases. In fact, non relational databases, such as redis, also support transactions. This paper mainly discusses how to use redis transactions in SpringBoot.
Please refer to the following for the relevant introduction of transactions:

0. Cause

In an online accident, we found that there was a large value in the use of redis, which exceeded the maximum data limit of dubbo, so we urgently split the large object value into a single string value.
In order to keep the database and redis double write consistent, the specified key should be deleted from redis when updating, deleting and inserting the database.
Everything is a routine operation using redis, but Lei is buried in the update method of one of the databases. In this method, transaction @ Transactional is turned on, resulting in the deletion of redis key.
Error report after online:


This error clearly indicates that redis in cluster mode does not support transactions. For reasons why the cluster does not support transactions, please refer to this article: Is there any Redis client (Java prefered) which supports transactions on Redis cluster?
Based on this problem, this paper summarizes the content of this paper

1. Transactions in Spring

All data access technologies have transaction mechanisms. These technologies provide API s to start transactions, commit transactions, complete data operations, or roll back data when errors occur.
Spring uses a unified mechanism to handle transactions of different data access technologies. Spring transactions provide an interface of platform transaction manager, and different data access technologies use different interfaces.

Data access technologyrealization
JDBCDataSourceTransactionManager
JPAJPATransactionManager
HibernateHibernateTransactionManager
JDOJDOTransactionManager
Distributed transactionJtaTransactionManager

Starting a transaction in SpringBoot is very simple. You only need to use the annotation @ Transactional on the method or class.
The Spring official document also requires @ EnableTransactionManagement to start transactions, but SpringBoot has already done it for us through automatic configuration, so we don't need to write this annotation in SpringBoot
Here we will focus on several common attributes of @ Transactional annotation

  • propagation

Transaction propagation mechanisms mainly include the following types. The default is REQUIRED:

  1. REQUIRED - Method A calls no transaction to create a transaction, invokes method B in method A, and uses the same transaction. If the method B is abnormal, it needs to roll back, and the whole transaction is rolled back.

  2. REQUIRES_NEW - when method A calls method B, A new transaction will be opened regardless of whether there is A transaction, so that the exception of method B will not cause the data rollback of method A.

  3. NESTED - and requirements_ New is similar, but only supports JDBC, not JPA or Hibernate

  4. SUPPORTS - when a method is called, transactions are used if there are transactions, and transactions are not used if there are no transactions

  5. NOT_SUPPORTED - force the method not to execute in the transaction. If there is a transaction, suspend the transaction from the method call to the end.

  6. NEVER - force no transaction. If there is a transaction, an exception will be thrown

  7. MANDATORY - MANDATORY transaction. If there is no transaction, an exception will be thrown

  • rollbackFor

Specify which exceptions can cause transaction rollback. By default, it is a subclass of Throwable

  • noRollbackFor

The default is the subclass of Throwable, which exceptions cannot be executed to cause transaction rollback

2. Failure of @ Transactional transactions

  1. Valid only for public methods. The default protected and private methods will not report an error if @ Transactional is written, but the transactions on this method will not take effect. The official original text: Method visibility and @Transactional
  2. By default (only write @ Transactional and do not fill in the rollbackFor parameter), this annotation will roll back the unchecked exception and will not roll back the checked exception;
  3. The method that does not open a transaction inside the class calls the method that opens the transaction
    The first two are easy to understand. For 3, I quote the explanation in Ding Xuefeng's Spring bucket:

Spring's declarative transactions essentially enhance the functionality of classes through AOP
Spring's AOP is essentially a proxy for a class

It seems to be calling the class written by yourself, but it actually uses the enhanced proxy class

The following figure describes the process when a method is represented by a transaction. Source: Spring AOP

3. Practice of integrating Redis transactions with SpringBoot

Let's build the simplest project of integrating redis with SpringBoot, and use code to verify redis transactions

  • Spring boot integrates Redis

Spring boot starter data redis is used by spring boot to integrate redis. Redis transactions depend on jdbc transaction management, so jdbc needs to be introduced
pom related introduction:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
  • Start Redis transaction

Write redis configuration class, start redis transaction and configure transaction management

@Configuration
public class RedisConfig {
    @Bean
    public StringRedisTemplate StringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        /**
         * description Start redis transaction (only stand-alone, not cluster)
         **/
        template.setEnableTransactionSupport(true);
        return template;
    }

    /**
     * description Configure transaction manager
     **/
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
}
  • Code verification

According to the discussion in this paper, four verification methods are designed, which can be verified by ourselves

    /**
     * description set without transaction
     * return java.lang.String
     * author Zheng Xiaolong
     * createTime 2019/12/12 16:36
     **/
    @GetMapping("put")
    public void put(String key, String value) {
        redisService.put(key, value);
    }

    /**
     * description With transaction set
     * return java.lang.String
     * author Zheng Xiaolong
     * createTime 2019/12/12 16:36
     **/
    @GetMapping("putWithTx")
    public void putWithTx(String key, String value) {
        redisService.putWithTx(key, value);
    }

    /**
     * description When calling the method with transaction does not take effect
     * return java.lang.String
     * author Zheng Xiaolong
     * createTime 2019/12/12 16:36
     **/
    @GetMapping("invokeWithPutTx")
    public void invokeWithPutTx(String key, String value) {
        redisService.invokePutWithTx(key, value);
    }

    /**
     * description When calling a method with transaction takes effect
     * return java.lang.String
     * author Zheng Xiaolong
     * createTime 2019/12/12 16:36
     **/
    @GetMapping("invokeWithPutTx2")
    public void invokeWithPutTx2(String key, String value) {
        redisService.invokePutWithTx2(key, value);
    }

4. Summary:

  • redis transaction only supports single machine, not cluster
  • When you need to start a transaction, you only need to use the @ Transactional annotation on the corresponding method or class. SpringBoot automatically starts @ EnableTransactionManagement
  • Attention should be paid to several situations in which transactions do not take effect
  • redis transactions depend on jdbc transaction management

5. Example code and reference:

Example code: redis transaction

  1. Transaction Management
  2. Transaction Propagation
  3. Transactional Support
  4. Spring bucket Ding Xuefeng

Topics: Redis