[SpringBoot] SpringBoot used redis Affairs

Based SpringBoot 2.X
affairs often used in the development of a relational database, in fact, non-relational databases, such as redis also has support for transactions, the paper discusses how to use redis transactions SpringBoot in.
Matters related presentations can refer to:

0, due

In a line in an accident, we locate the presence of a large value redis used, the amount of data exceeds the maximum limit dubbo, then this emergency large objects split value into a single string value.
In order to maintain the database and write the same redis double in the database update, delete, insert, delete from redis specified key.
Everything redis conventional operation, but mine buried in the update method in which a database, the open transaction @Transactional this method, which led to the deletion redis key operation also joined the transaction.
Error on line after:


The error made clear that, redis cluster model does not support transactions. The reason does not support transactions clusters can refer to the text: Is is there the any Redis Client (the Java prefered) Which the Supports Transactions ON Redis Cluster?
Based on this question, this article summarizes

1, Spring in the transaction

All data access technologies have transaction mechanism, these technologies provide an API to open the transaction, the transaction is committed to complete operational data or roll back data when the error occurred.
Spring unified mechanism to deal with matters of different data access technologies, Spring provides a transactional PlatformTransactionManagerinterface, different data access technology to use interface.

Data Access Technology achieve
JDBC DataSourceTransactionManager
JPA JPATransactionManager
Hibernate HibernateTransactionManager
Jdo JDOTransactionManager
Distributed Transaction JtaTransactionManager

Open in SpringBoot transaction is very simple, just use @Transactional to comment on the method or class.
Spring official document also requires @EnableTransactionManagement open transactions, but SpringBoot by automatically configuring has helped us to do, so do not write in the comment SpringBoot
highlight some notes here under @Transactional several common attributes

  • propagation

    Propagation mechanisms matters, mainly the following, the default is REQUIRED :
  1. REQUIRED - Method A calls a transaction when there is no new transaction, the call to B In Method A, using the same transaction, if an abnormality occurs Method B rollback, the entire transaction is rolled back.
  2. REQUIRES_NEW - When the method A calls method B, regardless of whether there are matters open a new transaction, so B does not cause abnormal method of data A rollback.

  3. NESTED - and REQUIRES_NEW similar, but only supports JDBC, Hibernate or JPA does not support
  4. SUPPORTS - there is a transaction to use the transaction method call, no transaction would not have affairs
  5. NOT_SUPPORTED - enforcement method is not performed within a transaction, if the transaction in the first stage of the method call to end the pending transaction.
  6. NEVER - can not be forced to have a transaction, if the transaction will throw an exception
  7. MANDATORY - must have forced the transaction, if the transaction does not throw an exception

  • rollbackFor

    Specify which exception can cause a rollback by default is a subclass of Throwable

  • noRollbackFor

    What causes abnormal transaction rollback is not available, the default is a subclass of Throwable execution

2, the case of failure of the transaction @ Transactional

  1. 只对public方法生效。默认的protected和private方法上写上@Transactional不会报错,但该方法上的事务不生效,官方原文:Method visibility and @Transactional
  2. 默认情况(只写@Transactional不填写rollbackFor参数)下此注解会对unchecked异常进行回滚,对checked异常不回滚;
  3. 类内部未开启事务的方法调用开启事务的方法
    前两条很好理解,针对3,引用丁雪丰的《Spring全家桶》视频中的解释:

Spring的声明式事务本质上是通过AOP来增强了类的功能
Spring的AOP本质上就是为类做了一个代理

看似在调用自己写的类,实际用的是增强后的代理类

下图描述了方法被事务代理时的流程,来源:Spring AOP

3、SpringBoot整合Redis事务实践

下面我们搭建一个最简单的SpringBoot整合redis的工程用代码来验证redis事务

  • SpringBoot整合Redis

    SpringBoot整合redis使用的是spring-boot-starter-data-redis,redis事务依赖于jdbc的事务管理,所以还需要引入jdbc
    pom相关引入:
        <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>
  • 开启Redis事务

    编写redis配置类,开启redis事务,配置事务管理
@Configuration
public class RedisConfig {
    @Bean
    public StringRedisTemplate StringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        /**
         * description 开启redis事务(仅支持单机,不支持cluster)
         **/
        template.setEnableTransactionSupport(true);
        return template;
    }

    /**
     * description 配置事务管理器
     **/
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
}
  • 代码验证

    针对本文讨论,设计了四个验证方法,可自行验证
    /**
     * description 不带事务set
     * return java.lang.String
     * author 郑晓龙
     * createTime 2019/12/12 16:36
     **/
    @GetMapping("put")
    public void put(String key, String value) {
        redisService.put(key, value);
    }

    /**
     * description 带事务set
     * return java.lang.String
     * author 郑晓龙
     * createTime 2019/12/12 16:36
     **/
    @GetMapping("putWithTx")
    public void putWithTx(String key, String value) {
        redisService.putWithTx(key, value);
    }

    /**
     * description 调用带事务方法不生效的情况
     * return java.lang.String
     * author 郑晓龙
     * createTime 2019/12/12 16:36
     **/
    @GetMapping("invokeWithPutTx")
    public void invokeWithPutTx(String key, String value) {
        redisService.invokePutWithTx(key, value);
    }

    /**
     * description 调用带事务方法生效的情况
     * return java.lang.String
     * author 郑晓龙
     * createTime 2019/12/12 16:36
     **/
    @GetMapping("invokeWithPutTx2")
    public void invokeWithPutTx2(String key, String value) {
        redisService.invokePutWithTx2(key, value);
    }

4、总结:

  • redis事务只支持单机,不支持cluster
  • 需要开启事务时,只需要在对应的方法或类上使用@Transactional注解即可,SpringBoot自动开启了@EnableTransactionManagement
  • 需要注意事务不生效的几种情况
  • redis事务依赖于jdbc的事务管理

5、示例代码及参考:

示例代码: redis-transaction

  1. Transaction Management
  2. Transaction Propagation
  3. Transactional Support
  4. 《Spring全家桶》丁雪丰

Guess you like

Origin www.cnblogs.com/zhengxl5566/p/12028293.html