SpringBoot中使用redis事务

JAVA SpringBoot中使用redis的事务 1、自定义redisConfig , 如果项目中要使用redis事务,最好将用事务和不用事务的redis分开。 阅读详情

本文基于SpringBoot 2.X
事务在关系型数据库的开发中经常用到,其实非关系型数据库,比如redis也有对事务的支持,本文主要探讨在SpringBoot中如何使用redis事务。
事务的相关介绍可以参考:

0、起因

在一次线上事故中,我们定位到redis的使用存在大value,超过了dubbo的最大数据量限制,于是紧急将这个大的对象value拆分成单个的string value。
为了保持数据库和redis双写一致,在对数据库进行更新,删除,插入操作时,要从redis删除指定的key。
一切都是使用redis的常规操作,但雷就埋在其中一个数据库的update方法里,这个方法上开启了事务@Transactional,导致里面的删除redis key操作也加入了事务。
上线后出现报错:


这个报错明确指出,集群模式的redis不支持事务。集群不支持事务的原因可参考此文:Is there any Redis client (Java prefered) which supports transactions on Redis cluster?
基于此次问题,总结出本文内容

1、Spring中的事务

所有数据访问技术都有事务机制,这些技术提供了API来开启事务、提交事务完成数据操作, 或者在发生错误的时候回滚数据。
Spring采用统一的机制来处理不同的数据访问技术的事务, Spring的事务提供一个PlatformTransactionManager的接口,不同的数据访问技术使用不同的接口实现。

数据访问技术实现
JDBCDataSourceTransactionManager
JPAJPATransactionManager
HibernateHibernateTransactionManager
JDOJDOTransactionManager
分布式事务JtaTransactionManager

在SpringBoot中开启事务非常简单,只需要在方法或类上使用注解@Transactional即可。
Spring官方文档中还要求使用@EnableTransactionManagement 开启事务,但SpringBoot通过自动配置已经帮我们做了,所以SpringBoot中不用写该注解
这里重点讲下@Transactional注解的几个常用属性

  • propagation

事务的传播机制,主要有以下几种,默认是REQUIRED:

  1. REQUIRED - 方法A调用时候没有事务新建一个事务,在方法A中调用方法B,将使用相同的事务,如果方法B发生异常需要回滚,整个事务回滚。

  2. REQUIRES_NEW - 方法A调用方法B时,无论是否存在事务都开启一个新事务,这样B方法异常不会导致A的数据回滚。

  3. NESTED - 和REQUIRES_NEW类似,但是只支持JDBC,不支持JPA或Hibernate

  4. SUPPORTS - 方法调用时有事务就用事务,没事务就不用事务

  5. NOT_SUPPORTED - 强制方法不在事务中执行,若有事务,在方法调用到结束阶段先挂起事务。

  6. NEVER - 强制不能有事务,若有事务就抛出异常

  7. MANDATORY - 强制必须有事务,如果没有事务就抛出异常

  • rollbackFor

指定哪些异常可以导致事务回滚,默认是Throwable的子类

  • noRollbackFor

执行哪些异常不可用引起事务回滚,默认是Throwable的子类

2、@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全家桶》丁雪丰
Redis 由浅入深 (8) - Springboot 中的Redis 事务使用 有一些场景我们可以在一段代码中多次操作redis,每次请求Redis都要去Jedis/Lettuce连接池申请一个连接请求一次redis服务进行缓存操作。 这样不仅有网络的消耗,假如在redis连接数吃紧的情况下多次请求redis很有可能回造成redis获取连接超时。懂得redis的兄弟这时候会说可以使用pipeline解决啊!确实我们使用pipeline批量命令去请求redis会解决上述问题,但还有一种场景就是我上一个redis请求成功了,但下一个请求失败了,这个时候上一个请求我需要回滚怎么办?..... 阅读详情

相关推荐

STM32CUBEMX配置SDRAM

STM32CUBEMX配置SDRAM

Master_0_的博客 2982

【redis系列】springboot使用redis事务

事务处理 redis事务提供了一种“将多个命令打包, 然后一次性、按顺序地执行”的机制, 并且事务在执行的期间不会主动中断 —— 服务器在执行完事务中的所有命令之后, 才会继续处理其他客户端的其他命令。 Redis中的事务是可以视为一个队列,即我们可以通过MULTI开始一个事务,这相当于我们声明了一个命令队列。 接下来,我们向Redis中提交的每条命令,都会被排入这个命令队列。 当我们输入EXEC命令时,将触发当前事务,这相当于我们从命令队列中取出命令并执行,所以Redis中一个事务从开始到执行会经历 开始

Think_and_work的博客 4411

Cadence ADE实战:1GHz VCO相位噪声仿真全流程(附PSS/Pnoise避坑指南)

本文详细介绍了在Cadence ADE环境中对1GHz VCO进行相位噪声仿真的完整流程。重点剖析了PSS(周期性稳态分析)和Pnoise(周期性噪声分析)两大核心引擎的关键参数设置与避坑指南,帮助射频与模拟IC设计者准确评估VCO性能,解决仿真不收敛、结果异常等常见问题。

rock5的博客 669

springboot使用redis事务

Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。标记一个事务块的开始。执行所有事务块的命令。

justlpf的专栏 1269

unity中VideoPlayer播放视频,使用Shader除去黑底且无黑边

1. 创建一个Shader 和 一个 材质球;Shader中复制如下代码:(此Shader代码为“ChromaKeyKit”插件中的ChromaKey_Alpa_Genera代码,但因只需要除去视频黑底而挂一个插件有点不合适) // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "ChromaKeyKit/ChromaKey/ChromaKey_Alpha_General"

weixin_42065078的博客 1747

告别手动烧录!给STM32H750外挂Flash制作Keil专用下载算法(保姆级避坑指南)

本文详细介绍了为STM32H750外挂Flash开发Keil专用下载算法的全过程,从原理到实战操作,特别针对QSPI Flash的配置和优化提供了保姆级避坑指南。通过定制下载算法,开发者可以告别手动烧录,实现一键下载到外部Flash,大幅提升开发效率。

weixin_42567497的博客 250

springboot使用redis的事务

redis事务 Redis 事务的命令: 开启事务:multi 命令入队 执行事务:exec 撤销事务:discard 概述 在SpringBoot中,开启Redis的事务有两种方式,一种是手动开启,一种是使用@Transaction注解。 使用注解方式 redis配置类 //springBoot会自动配置redis,具体可参照RedisAutoConfiguration.java,但是默认的配置,没有开启事务,所以需要自定义 @Configuration @EnableConfigurationPrope

fall_hat的博客 2166

卷积神经网络-猫狗识别(附源码)

利用python实现一个卷积神经网络,训练猫狗数据集,实现对猫狗图片的预测识别

m0_63223213的博客 2万+

spring boot 事务_Redis 事务在 SpringBoot 中的应用

环境信息JDK 版本信息<properties> <java.version>1.8</java.version> </properties>SpringBoot 版本、依赖信息<parent> <groupId>org.springframework.boot</groupId> <artifa...

weixin_39915267的博客 226

OpenClaw 多代理协同工作模式配置指南

OpenClaw 采用。

形上得其象,形下合于数;阴阳自济,玄理自明。 1万+

EtherCAT主站SOEM -- 0 -- 该EtherCAT主站SOEM专栏后续安排

SOEM(Simple Open EtherCAT Master)是一个开源的EtherCAT主站库,允许开发者构建自定义的EtherCAT主站应用程序。EtherCAT是一种实时以太网通信协议,广泛应用于工业自动化和机器控制领域。开源性质:SOEM是一个开源项目,这意味着开发者可以自由地查看、修改和分发代码。这使其成为工业自动化领域的一个强大工具,可以根据具体需求进行定制。EtherCAT主站实现:SOEM库提供了一个完整的EtherCAT主站实现,允许主站与多个EtherCAT从站设备进行通信。

常驻客栈的博客--嵌入式EtherCAT 6664

Redis事务机制详解与Springboot项目中的使用

在 Spring Boot 中使用 Redis 事务机制时,可以通过。

专注于技术分享 1414

SwiftUI 5 教程之 SwiftData使用入门(教程含源码)

对我来说,记住日期很难。是的,您可以设置该日期的提醒,但该提醒无法产生紧迫感。让我们创建一个应用程序,我们可以在其中添加将来发生的事件。如果我们可以在主应用程序上看到所有即将发生的活动,那就太好了。也许将它们添加到小部件上以营造紧迫感。对于任何事件,我们需要跟踪哪些事情?我们将在下一篇文章中添加更多属性,其中我们将讨论迁移。现在,这就是我们所需要的。开始吧。

iCloudEnd的博客 987

SpringBoot 实现 redis 事务

在这个例子中,redisTemplate.setEnableTransactionSupport(true)用于启用事务支持,redisTemplate.multi()用于开启事务,redisTemplate.exec()用于提交事务,如果中间出现异常,则调用redisTemplate.discard()取消事务。选择哪种方式取决于具体的业务需求和使用场景。通常,使用Spring Data Redis的SessionCallback是较为直接和简便的方法,但对于更复杂的需求,可以考虑使用Lua脚本。

Happy_lifer的博客 506

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

SpringBoot整合Redis事务全解析

需要注意的是Redis事务操作并不像是关系型数据库那样具有原子性和隔离性,根据上面的介绍Redis事务操作其实是一组命令的集合,而这些命令是按它们在事务执行过程中的顺序来执行的,并且在事务执行过程中不会被其他的客户端打断。但是,如果其中一个命令执行失败,Redis不会回滚之前已经执行成功的命令,这需要开发者自己处理。这是什么意思呢?就是说在事务中的命令要么全部成功要么全部失败,但是如果对于mulit、exec这样的命令如果执行失败了,那么依旧是无法保证事务操作的。

2501_93873871的博客 877

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Redis-redis事务、乐观锁、Jedis、SpringBoot整合Redis

Redis 事务本质: 一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程的中,会按照顺序执行 ! 一次性、顺序性、排他性! 执行一些列的命令! Redis事务没有没有隔离级别的概念! 所有的命令在事务中,并没有直接被执行! 只有发起执行命令的时候才会执行! Exec Redis单条命令是保证原子性的,但是事务不保证原子性! 本文介绍了reids事务、乐观锁的配置,理解Jedis,并使用SpringBoot整合redis

小孔靠得住的博客 1423

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Redis事务、Jedis、SpringBoot整合Redis

学习视频链接,示以尊重:https://space.bilibili.com/95256449/video 一、Redis 事务 Redis 事务本质:一组命令的集合。一个事务中的所有命令都会被序列化,在事务执行过程的中,会按照顺序执行。(一次性、顺序性、排他性) 注意: Redis 单条命令是保证原子性的,但是 Redis 的事务不保证原子性 Redis 事务没有隔离级别的概念 所有的命令在事务中,并没有直接被执行。只有发起执行命令的时候才会执行 Redis 事务执行阶段: 开启事务:multi

一只黑猩猩 528

springboot中使用redis事务

目录 前言 代码演示 1.RedisService 工具类中增加三个方法 2.测试类中添加测试方法 前言 上篇我们通过redis的原始命令了解了redis的事务机制,本篇结合springboot简单了解下redis的事务使用方式,各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢! 代码演示 1.RedisService 工具类中增加三个方法 /** * 开启事务 * @return */ pu

FAIRYTAIL的博客 886

在 SpringBoot 2.x 中使用 @Transactional 对 Redis 事务管理

一.添加 Redis 基础配置 spring: redis: host: 127.0.0.1 port: 6379 password: 二.开启 Redis 事务配置 @Configuration @EnableTransactionManagement // 1 public class RedisConfig { @Bean public Stri...

因特马 1万+

在Spring Boot中Redis实现事务有哪些方式?

以上三种方式都可以在Spring Boot中实现对Redis的事务支持。选择哪种方式取决于具体的业务需求和使用场景。通常,使用Spring Data Redis的SessionCallback是较为直接和简便的方法,但对于更复杂的需求,可以考虑使用Lua脚本。

主要作为个人的笔记用,Not For Everyone。 843
上一篇: 重新学习Mysql数据库4:Mysql索引实现原理和相关数据结构算法
下一篇: SpringBoot注解详解
wrr-cat
博客等级 码龄9年 128粉丝 302原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值