大家好,我是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事务-亲测的更多相关文章

  1. Windows环境下springboot集成redis的安装与使用

    一,redis安装 首先我们需要下载Windows版本的redis压缩包地址如下: https://github.com/MicrosoftArchive/redis/releases 连接打开后如下 ...

  2. 【springBoot】springBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...

  3. SpringBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...

  4. springboot集成redis(mybatis、分布式session)

    安装Redis请参考:<CentOS快速安装Redis> 一.springboot集成redis并实现DB与缓存同步 1.添加redis及数据库相关依赖(pom.xml) <depe ...

  5. springBoot集成Redis遇到的坑(择库)源码分析为什么择库失败

    提示: springboot提供了一套链接redis的api,也就是个jar包,用到的连接类叫做LettuceConnectionConfiguration,所以我们引入pom时是这样的 <de ...

  6. SpringBoot | 集成Redis

    Windows下安装: https://github.com/MicrosoftArchive/redis/releases zip下就解包到自定义目录下,msi就跟着步骤安装 进入安装目录下运行命令 ...

  7. springboot集成redis使用redis作为session报错ClassNotFoundException类RememberMeServices

    springboot 集成redis使用redis作为缓存,会报错的问题. 错误信息: java.lang.IllegalStateException: Error processing condit ...

  8. Springboot集成Redis步骤

    Spring boot 集成Redis的步骤如下: 1.在pom.xml中配置相关的jar依赖: <!--加载spring boot redis包 --> <dependency&g ...

  9. SpringBoot集成Redis

    1.引入 spring-boot-starter-redis <dependency> <groupId>redis.clients</groupId> <a ...

  10. SpringBoot集成Redis分布式锁以及Redis缓存

    https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...

随机推荐

  1. Windows11右键菜单修改为Win10模式的方法

    Windows11右键菜单修改为Win10模式的方法 自述: 更新win11后看着鼠标右键的菜单有些不太舒服,索性就改回了win10的右键菜单的样式 , 下面开始进行操作 第一步 首先以管理员方式打开 ...

  2. 编译器性能调优:使用C++11实现高效编译器

    目录 1. 引言 2. 技术原理及概念 2.1. 基本概念解释 2.2. 技术原理介绍 <编译器性能调优:使用C++11实现高效编译器> 编译器是计算机程序的入口点,将源代码转换为可执行文 ...

  3. ASP.NET Core 6框架揭秘实例演示[41]:跨域资源的共享(CORS)花式用法

    同源策略是所有浏览器都必须遵循的一项安全原则,它的存在决定了浏览器在默认情况下无法对跨域请求的资源做进一步处理.为了实现跨域资源的共享,W3C制定了CORS规范.ASP.NET利用CorsMiddle ...

  4.  Python + unittest + ddt + HTMLTestRunner + log + excel + mysql + 企业微信通知, 接口自动化框架V2.0,支持多业务处理,仅需维护 excel 用例,无需要编写代码

    Python + unittest + ddt + HTMLTestRunner + log + excel + mysql + 企业微信通知 + Jenkins 实现的接口自动化框架. 项目介绍 接 ...

  5. Elasticsearch日常开发

    2020-08-12 14:51:37 每次遇到ES开发,一般都是查询es里面的数据,今天我教大家一个简单的es的查询.废话不多说,直接上代码. 在pom文件中引入 <dependency> ...

  6. 再见RestTemplate,Spring 6.1新特性:RestClient 了解一下!

    在最近发布的Spring 6.1 M2版本中,推出了一个全新的同步HTTP客户端:RestClient.用一句话来让Spring开发者认识RestClient的话:像WebClient一样具备流畅AP ...

  7. C语言基础-基础指针

    文章目录 指针 前言 1.什么是指针 2.指针的使用 (1)指针的定义 (2)指针的赋值 (3)指针类型 (4)如何使用指针 3.野指针 (1)导致野指针的原因 ① 未初始化指针 ②指针越界访问 ③指 ...

  8. JVM运行时数据区之堆空间

    JVM运行时数据区之堆空间 1.核心概述 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域.堆区在JVM 启动的时候即被创建,其空间大小也就确定了,是JVM管理的最大一块内存空间. & ...

  9. web系统字典统一中文翻译问题

    几乎每个web系统都离不开各种状态码.订单新建,待支付,未支付,已支付,待发货. 消息已读未读,任务待标记待审批已审批待流转已完成未完成.等等. 复杂一点的,会有多级状态码. 状态码超出3个的,一般都 ...

  10. Linux 命令:grub2-mkconfig

    检索这个命令的,肯定都知道 grub 是 bootloader 程序,用于引导系统启动.配置文件是 grub.conf,现在一般的 grub 版本是grub2. 当机器上安装有多个内核.或者多个操作系 ...