[SpringBoot]SpringBoot中使用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
的接口,不同的数据访问技术使用不同的接口实现。
数据访问技术 | 实现 |
---|---|
JDBC | DataSourceTransactionManager |
JPA | JPATransactionManager |
Hibernate | HibernateTransactionManager |
JDO | JDOTransactionManager |
分布式事务 | JtaTransactionManager |
在SpringBoot中开启事务非常简单,只需要在方法或类上使用注解@Transactional即可。
Spring官方文档中还要求使用@EnableTransactionManagement 开启事务,但SpringBoot通过自动配置已经帮我们做了,所以SpringBoot中不用写该注解
这里重点讲下@Transactional注解的几个常用属性
propagation
事务的传播机制,主要有以下几种,默认是REQUIRED:
REQUIRED - 方法A调用时候没有事务新建一个事务,在方法A中调用方法B,将使用相同的事务,如果方法B发生异常需要回滚,整个事务回滚。
REQUIRES_NEW - 方法A调用方法B时,无论是否存在事务都开启一个新事务,这样B方法异常不会导致A的数据回滚。
NESTED - 和REQUIRES_NEW类似,但是只支持JDBC,不支持JPA或Hibernate
SUPPORTS - 方法调用时有事务就用事务,没事务就不用事务
NOT_SUPPORTED - 强制方法不在事务中执行,若有事务,在方法调用到结束阶段先挂起事务。
NEVER - 强制不能有事务,若有事务就抛出异常
MANDATORY - 强制必须有事务,如果没有事务就抛出异常
rollbackFor
指定哪些异常可以导致事务回滚,默认是Throwable的子类
noRollbackFor
执行哪些异常不可用引起事务回滚,默认是Throwable的子类
2、@Transactional事务失效的情况
- 只对public方法生效。默认的protected和private方法上写上@Transactional不会报错,但该方法上的事务不生效,官方原文:Method visibility and @Transactional;
- 默认情况(只写@Transactional不填写rollbackFor参数)下此注解会对unchecked异常进行回滚,对checked异常不回滚;
- 类内部未开启事务的方法调用开启事务的方法
前两条很好理解,针对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、示例代码及参考:
- Transaction Management
- Transaction Propagation
- Transactional Support
- 《Spring全家桶》丁雪丰
欢迎扫码关注我的个人公众号,获取最新文章↓
[SpringBoot]SpringBoot中使用redis事务的更多相关文章
- Spring-Boot项目中配置redis注解缓存
Spring-Boot项目中配置redis注解缓存 在pom中添加redis缓存支持依赖 <dependency> <groupId>org.springframework.b ...
- SpringBoot项目中,Redis的初次使用
1.引入Redis依赖包,在application.yml中配置redis <dependency> <groupId>org.springframework.boot< ...
- Spring Framework 中启动 Redis 事务操作
背景: 项目中遇到有一系列对Redis的操作,并需要保持事务处理. 环境: Spring version 4.1.8.RELEASE Redis Server 2.6.12 (64位) spring- ...
- spring的声明式事务,及redis事务。
Redis的事务功能详解 http://ghoulich.xninja.org/2016/10/12/how-to-use-transaction-in-redis/ MULTI.EXEC.DISCA ...
- 由浅入深学习springboot中使用redis
很多时候,我们会在springboot中配置redis,但是就那么几个配置就配好了,没办法知道为什么,这里就详细的讲解一下 这里假设已经成功创建了一个springboot项目. redis连接工厂类 ...
- 在SpringBoot中引入Redis
前言 之前我们只是在Spring中加入Redis用于session的存放,并没有对redis进行主动的存放,这次我们需要加入redis工具类来方便我们在实际使用过程中操作redis 已经加入我的git ...
- SpringBoot中集成redis
转载:https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html 不是使用注解而是代码调用 需要在springbo ...
- (一)由浅入深学习springboot中使用redis
很多时候,我们会在springboot中配置redis,但是就那么几个配置就配好了,没办法知道为什么,这里就详细的讲解一下 这里假设已经成功创建了一个springboot项目. redis连接工厂类 ...
- SpringBoot中使用Redis
在SpringBoot中使用Redis,思路如下: 查询时先查Redis缓存,如果缓存中存在信息,就直接从缓存中获取. 如果缓存中没有相关信息,就去数据库中查找,查完顺便将信息存放进缓存里,以便下一次 ...
随机推荐
- hibernate中的映射
hibernate中的映射是指Java类和数据库表中的属性来进行关联,然后通过类来操作数据库中,这就是简单的映射.
- VMware15 镜像Centos7修改静态IP
VMware15 镜像Centos7修改静态IP * 我的网卡名称为ens33: * 配置IP在 /etc/sysconfig/network-scripts/ifcfg-ens33 目录下: * D ...
- CentOS6.5 开机启动自动运行redis服务
[一].查找和设置自己的redis路径参数 环境变量 PATH=/usr/local/bin:/sbin/:/usr/bin:/bin 端口 REDISPORT=6379 文件位置 EXEC=/usr ...
- TensorFlow从0到1之回归算法(11)
回归是数学建模.分类和预测中最古老但功能非常强大的工具之一.回归在工程.物理学.生物学.金融.社会科学等各个领域都有应用,是数据科学家常用的基本工具. 回归通常是机器学习中使用的第一个算法.通过学习因 ...
- elasticsearch unassigned shards 导致RED解决
先通过命令查看节点的shard分配整体情况 curl -X GET "ip:9200/_cat/allocation?v" 说明:有16个索引未分片 2.查看未分片的索引 curl ...
- 这一次搞懂SpringMVC原理
@ 目录 前言 正文 请求入口 组件初始化 调用Controller 参数.返回值解析 总结 前言 前面几篇文章,学习了Spring IOC.Bean实例化过程.AOP.事务的源码和设计思想,了解了S ...
- C# WPF - MVVM实现OPC Client管理系统
前言 本文主要讲解采用WPF MVVM模式设计OPC Client的过程,算作对于WPF MVVM架构的学习记录吧!不足之处请不吝赐教,感谢! 涉及知识点 C#基础 Xaml基础 命令.通知和数据绑定 ...
- CODING DevOps 系列第三课:云计算、云原生模式下 DevOps 的建设
本文首先会和大家分享当前整个应用生命周期的演变历程,然后讲解云计算模式下 DevOps 建设包含的过程.流程规范和标准,最后讲解云原生时代到来会带来哪些改变,以及标准化的建设会有哪些改变和突破. 应用 ...
- 【String注解驱动开发】面试官让我说说:如何使用FactoryBean向Spring容器中注册bean?
写在前面 在前面的文章中,我们知道可以通过多种方式向Spring容器中注册bean.可以使用@Configuration结合@Bean向Spring容器中注册bean:可以按照条件向Spring容器中 ...
- ADB命令 使用
简介 ADB,即 Android Debug Bridge ,它是 Android 开发/测试人员不可替代的强大工具 .安卓调试桥 (Android Debug Bridge, adb),是一种可以 ...