【Redis】SpringBoot集成Redis事务-亲测
大家好,我是mep。今天一起来探讨一下Redis缓存的问题,SpringBoot如何集成Redis网上文章很多,基本都是介绍如何配置redisTemplate,如何调用,本文就不过多介绍了。这次我们研究的是:Redis的事务。
首先抛出一个问题,Redis支持事务吗?
答案肯定是支持,不然也不需要我们在这里探讨了。
然后你拿到关键词"Redis 事务"去搜索引擎搜索一下,得到了这样的答案:
Redis支持事务,But!Redis的事务不保证原子性,事务不会回滚。例如:我在Redis中提交了一个事务,包含3条命令,其中第2条命令报错了,并不会导致第一条命令的回滚,也不会阻止第三条命令的执行。
可是,真的是这样吗?你试过吗?哈哈,知道你们懒得试,我来帮你们试试看喽!

先看一个我自己测试的例子,以下例子中RedisTemplate都开启了事务支持,否则测试没有意义,我的RedisConfiguration代码如下:
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setEnableTransactionSupport(true);
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
然后让我们来看几个例子:
例1,使用@Transactional注解,方法执行过程中报错,代码如下:
@Transactional
public void testRedisTransaction() {
employeeMapper.updateByPrimaryKey(Employee.builder()
.id(4L)
.name("uuuuu")
.gender(Gender.MALE)
.build());
redisTemplate.opsForValue().set("111", "111");
int i = 1 / 0;
redisTemplate.opsForValue().set("222", "111");
}
执行前Redis缓存情况:

执行以上方法后,肯定会报错:
java.lang.ArithmeticException: / by zero
猜猜执行完后数据库和Redis中数据操作是什么样的?

1.数据库会回滚,即update无效,这个并不意外,没啥可说的
2.执行后Redis缓存情况:

空的?不是说Redis的事务不支持回滚吗?为什么key修改却无效了呢?
确实,因为Redis根本没有回滚,它的事务压根就没有提交!!!
这就是Redis的事务和关系型数据库不一样的地方,数据库一个事务中如果某一条SQL报错或方法中有RuntimeException(@Transactional默认)抛出的话,事务会回滚。对于Redis的事务来说,如果方法中抛RuntimeException的话,事务压根不提交,被DISCARD之后,自然不会执行。
如果你看到这里了,说明你一开始就质疑最上面搜索到的结果,连查到的知识都会质疑和验证,为什么要相信我上面说的事务压根就没有提交的结论呢?
带着疑问,我们继续验证,先上代码:
@Transactional
public void testRedisTransaction() {
employeeMapper.updateByPrimaryKey(Employee.builder()
.id(4L)
.name("uuuuu")
.gender(Gender.MALE)
.build());
System.out.println(1234);
redisTemplate.opsForValue().set("111", "a");
redisTemplate.opsForValue().set("222", "a");
redisTemplate.exec();
int i = 1 / 0;
}
这次主动在报异常前提交了Redis事务,结果如下:

到这里,我们得到结论是这样的:
Redis事务不能回滚,方法报异常时事务并没有回滚,之所以数据没有被写入到Redis,是因为事务被DISCARD了
根据我们查到的内容,还需要验证Redis的事务不能保证原子性,继续上示例:
例2,使用@Transactional注解,在Redis事务中报错,代码如下:
@Transactional
public void testRedisTransactionOnly() {
redisTemplate.opsForValue().set("333", "a");
redisTemplate.opsForHash().put("333", "a", 111);
}
正常来说,应该会报WRONGTYPE Operation的错误,不过,执行结果是这样的:

甚至,连个错误都没有报!
是代码的问题吗?还是因为Redis的事务忽略了异常的命令,只执行了正常的命令?
继续测试,清空Redis,去掉@Transactional注解:
// @Transactional
public void testRedisTransactionOnly() {
redisTemplate.opsForValue().set("333", "a");
redisTemplate.opsForHash().put("333", "a", 111);
}
执行结果:

可见代码没有问题,确实会报错,只是提交到一个事务中,它不保证原子性,只执行了可执行的命令,即使后续的命令报错,也不会回滚,而且不会报错。
至此,Redis事务相关的验证已结束。
结论就是我们开始搜索到的结果:
Redis支持事务,But!Redis的事务不保证原子性,事务不会回滚,提交后会执行可正常执行的命令,忽略报错的命令。
最后,来自Redis官网的一句话佐证我们的结论, 附出处:Transactions | Redis

【Redis】SpringBoot集成Redis事务-亲测的更多相关文章
- Windows环境下springboot集成redis的安装与使用
一,redis安装 首先我们需要下载Windows版本的redis压缩包地址如下: https://github.com/MicrosoftArchive/redis/releases 连接打开后如下 ...
- 【springBoot】springBoot集成redis的key,value序列化的相关问题
使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...
- SpringBoot集成redis的key,value序列化的相关问题
使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...
- springboot集成redis(mybatis、分布式session)
安装Redis请参考:<CentOS快速安装Redis> 一.springboot集成redis并实现DB与缓存同步 1.添加redis及数据库相关依赖(pom.xml) <depe ...
- springBoot集成Redis遇到的坑(择库)源码分析为什么择库失败
提示: springboot提供了一套链接redis的api,也就是个jar包,用到的连接类叫做LettuceConnectionConfiguration,所以我们引入pom时是这样的 <de ...
- SpringBoot | 集成Redis
Windows下安装: https://github.com/MicrosoftArchive/redis/releases zip下就解包到自定义目录下,msi就跟着步骤安装 进入安装目录下运行命令 ...
- springboot集成redis使用redis作为session报错ClassNotFoundException类RememberMeServices
springboot 集成redis使用redis作为缓存,会报错的问题. 错误信息: java.lang.IllegalStateException: Error processing condit ...
- Springboot集成Redis步骤
Spring boot 集成Redis的步骤如下: 1.在pom.xml中配置相关的jar依赖: <!--加载spring boot redis包 --> <dependency&g ...
- SpringBoot集成Redis
1.引入 spring-boot-starter-redis <dependency> <groupId>redis.clients</groupId> <a ...
- SpringBoot集成Redis分布式锁以及Redis缓存
https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...
随机推荐
- Adobe 构建 IDP 之路的经验与教训
在过去的25年多时间里,我创建了软件组件和分布式框架,建立并领导了相关团队.近几年我致力于推动 Adobe 服务开发.部署和管理系统的开发人员生产力. 抽象陷阱 在云时代早期,Adobe 的每个团队都 ...
- 如何洞察 C# 程序的 GDI 句柄泄露
一:背景 1. 讲故事 前段时间有位朋友找到我,说他的程序界面操作起来很慢并且卡顿等一些不正常现象,从任务管理器看了下 GDI句柄 已经到 1w 了,一时也找不出什么代码中哪里有问题,让我帮忙看下,其 ...
- 【Leetcode】 #9 回文数
判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数.示例 1:输入: 121输出: true示例 2:输入: -121输出: false解释: 从左向右读, 为 - ...
- CSS3实现嵌套立方体旋转的3D效果
刚发现一个网站上面的3D立方体效果挺好看的,就模仿着用CSS3实现了一个类似的效果:http://39.105.101.122/myhtml/CSS/transform_3D/cube_3D.html ...
- Python运维开发之路《编程》
一.编程思想介绍 1.编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现 ...
- 1.6 编写双管道ShellCode后门
本文将介绍如何将CMD绑定到双向管道上,这是一种常用的黑客反弹技巧,可以让用户在命令行界面下与其他程序进行交互,我们将从创建管道.启动进程.传输数据等方面对这个功能进行详细讲解.此外,本文还将通过使用 ...
- vscode中react组件
通过使用这个插件我们可以很方便的进行组件/方法/文件的导入 本篇博客仅对插件进行介绍翻译,便于自己以后使用 常用片段列表 imr: 引入 React import React from 'react' ...
- 每日一题:SpringBoot中支持的事务类型
以下是每种事务类型的作用.代码示例和对代码的解释: PROPAGATION_REQUIRED(默认): 作用:如果当前存在事务,则方法将在该事务中运行:如果不存在事务,则创建一个新的事务.适用于大多数 ...
- MyBatis使用注解开发(及Sqlsession连接器的本质)
使用注解开发 底层实现机制是反射和,动态代码.反射可以获得这个类的方法属性还可以创建对象,执行方法. 面向接口编程 之前学过,面向对象编程,也学习过接口.但是真正的开发中,很多时候我们会选择面向接口编 ...
- 使用Locust进行分布式性能测试
Locust是一个强大的性能测试工具,用于评估系统的性能和可扩展性.本文将简洁地介绍使用Locust进行分布式性能测试的步骤和优势. 步骤: 1. 配置测试环境:在主节点和多个从节点上安装相同版本的L ...