【Redis】Redis事务:原子性与回滚的真相揭秘

这篇具有很好参考价值的文章主要介绍了【Redis】Redis事务:原子性与回滚的真相揭秘。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

大家好,我是mep。今天一起来探讨一下Redis缓存的问题,SpringBoot如何集成Redis网上文章很多,基本都是介绍如何配置redisTemplate,如何调用,本文就不过多介绍了。这次我们研究的是:Redis的事务。

首先抛出一个问题,Redis支持事务吗?

 

【Redis】Redis事务:原子性与回滚的真相揭秘

 

答案肯定是支持,不然也不需要我们在这里探讨了。

然后你拿到关键词"Redis 事务"去搜索引擎搜索一下,得到了这样的答案:

Redis支持事务,But!Redis的事务不保证原子性,事务不会回滚。例如:我在Redis中提交了一个事务,包含3条命令,其中第2条命令报错了,并不会导致第一条命令的回滚,也不会阻止第三条命令的执行。

可是,真的是这样吗?你试过吗?哈哈,知道你懒得试,我来帮你们试试看喽!

【Redis】Redis事务:原子性与回滚的真相揭秘

先看一个我自己测试的例子,以下例子中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缓存情况:

【Redis】Redis事务:原子性与回滚的真相揭秘

执行以上方法后,肯定会报错:

java.lang.ArithmeticException: / by zero

猜猜执行完后数据库和Redis中数据操作是什么样的?

 

【Redis】Redis事务:原子性与回滚的真相揭秘

1.数据库会回滚,即update无效,这个并不意外,没啥可说的

2.执行后Redis缓存情况:

【Redis】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事务:原子性与回滚的真相揭秘

 到这里,我们得到结论是这样的:

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事务:原子性与回滚的真相揭秘

 甚至,连个错误都没有报!

是代码的问题吗?还是因为Redis的事务忽略了异常的命令,只执行了正常的命令?

继续测试,清空Redis,去掉@Transactional注解:

//    @Transactional
    public void testRedisTransactionOnly() {
        redisTemplate.opsForValue().set("333", "a");
        redisTemplate.opsForHash().put("333", "a", 111);
    }

执行结果:

【Redis】Redis事务:原子性与回滚的真相揭秘

 可见代码没有问题,确实会报错,只是提交到一个事务中,它不保证原子性,只执行了可执行的命令,即使后续的命令报错,也不会回滚,而且不会报错

至此,Redis事务相关的验证已结束。

结论就是我们开始搜索到的结果:

Redis支持事务,But!Redis的事务不保证原子性,事务不会回滚,提交后会执行可正常执行的命令,忽略报错的命令。

最后,来自Redis官网的一句话佐证我们的结论, 附出处:Transactions | Redis

【Redis】Redis事务:原子性与回滚的真相揭秘文章来源地址https://www.toymoban.com/news/detail-712129.html

到了这里,关于【Redis】Redis事务:原子性与回滚的真相揭秘的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Jenkins CICD的代码发布与回滚 Jenkins+Git+Docker 发布 Java 项目 Jenkins+Git+Ansible 发布PHP 项目

    目录 案例概述 案例环境 基于 Jenkins+Git+Docker 发布 Java 项目 1、配置 Git 仓库 2、配置 Docker服务器 3、部署镜像仓库 5、配置Jenkins 环境 6、Jenkins 创建项目并发布测试 7、版本回滚 基于Jenkins+Git+Ansible 发布PHP 项目 1、部署PHP 运行环境 2、安装Ansible 插件 3、上传PHP 项目代码到Git仓

    2024年02月03日
    浏览(41)
  • AI写作:是助手还是威胁?揭秘七大疑虑与真相

    大家好,小发猫降重今天来聊聊AI写作:是助手还是威胁?揭秘七大疑虑与真相,希望能给大家提供一点参考。 以下是针对论文重复率高的情况,提供一些修改建议和技巧,可以借助此类工具: AI写作:是助手还是威胁?揭秘七大疑虑与真相 在自媒体时代,AI写作逐渐崭露头

    2024年03月16日
    浏览(43)
  • 矿机挖币真相揭秘:是财富梦想还是骗局一场

    矿机挖币真相揭秘:是财富梦想还是骗局一场? 矿机挖币,作为区块链技术的一部分,本质上是通过计算力竞争解决数学难题,以获得新区块的记账权并获取相应加密货币奖励的过程。这一机制的设计初衷是为了保证区块链网络的安全、去中心化以及交易的不可篡改性。在这

    2024年04月12日
    浏览(39)
  • 大数据小白初探HDFS架构原理:带你揭秘背后的真相(一)

             目录 1.前言 2. HDFS架构 2.1 架构定义 2.2 揭秘架构 2.3 HDFS核心结构  3. HDFS 的优缺点         3.1 HDFS 的优点         3.2 HDFS 的缺点 4. HDFS 的应用场景 5. 总结         前面的文章写了一篇,大数据方面的基础知识,目的是希望大数据小白可以对大数据能有个清楚

    2024年02月21日
    浏览(49)
  • spring 只读事务 设置异常回滚事务

    @Transactional(readOnly = true) 将当前事务设置为只读事务,在该事务执行过程中只允许select语句执行,delete insert update均不可执行。 该特性的作用是: 启动spring的优化策略。提高select语句执行效率。 @Transactional(rollbackFor = RuntimeException.class) 表示只有发生RuntimeException异常或该异常的

    2024年02月09日
    浏览(34)
  • Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)

    事务定义 事务,就是一组操作数据库的动作集合。事务是现代数据库理论中的核心概念之一。如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行,我们称该事务被提交。由于其中的一部分或多步执

    2024年04月17日
    浏览(29)
  • 多线程事务怎么回滚?

    项目中用到了多线程去批量处理一些数据,当时想当然认为只要方法上加上@Transactional注解就好了,实际并未达到想要的处理效果。特此去学习了下关于多线程事务回滚相关方案,参考了网上其他资料,这里整理并记录下学习历程。 站在巨人的肩膀上,我们可以看的更远!

    2024年02月13日
    浏览(38)
  • Spring控制事务回滚

    1、Spring中开启事务的方式主要有两种: 编程式事务和声明式事务 。 2、事务是我们开发过程中经常会使用到的,为了在业务执行过程中出现异常时,回滚到原始状态。而事务的回滚在大多数情况下都是靠着 exception (异常)来触发回滚的,当事务机制捕捉到异常,就会开始回

    2024年02月09日
    浏览(35)
  • 【Java当中让事务回滚】

    在 Java 中,可以通过使用事务来保证数据库操作的一致性和完整性。如果在事务过程中发生了异常或错误,需要将事务回滚,以保证数据的正确性和完整性。 下面是在 Java 中让事务回滚的几种方式: 使用 Spring 事务管理:在 Spring 中,可以使用 @Transactional 注解来标记需要进行

    2024年02月11日
    浏览(32)
  • spring 事务回滚失败异常

    事务模板里抛异常,抛异常前的update操作成功,事务没有回滚成功,业务数据还是落db了。debug代码,发现GenericConnectionContext类中derivedConnectionMap是空的,导致回滚代码没有执行 保证事务内所有的 DAO 操作所涉及的数据源和事务模板所关联的数据源都是同一个对象, bundle 都是

    2024年02月13日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包