Spring Data Redis事务的正确使用姿势

Spring Data Redis 实战指南 通过@RedisHash注解定义Redis存储结构,该注解需指定哈希前缀值作为领域模型的命名空间标识。实体类需使用@Id标注主键字段,存储时将自动组合为[前缀]:[ID值]@Data@Id// 其他字段...Spring Data Redis 提供了完整的 Redis 集成解决方案,通过注解驱动开发模式显著提升了开发效率。与 Spring Boot 的深度集成简化了配置流程,开发者可以快速实现多种数据结构的灵活存储。开发效率@RedisHash等注解自动处理对象-存储映射,接口免除样板代码。 阅读详情

之前使用Spring Data Redis的时候,由于使用不当,导致redis连接不释放的血案。现在来总结下Spring Data Redis事务的两种使用方式。

1、execute(SessionCallback session)方法

我们都知道Redis的事务的命令主要有multi、exec、discard和watch,在RedisTemplate中也是对应的有这几种方法

  public interface RedisOperations<K, V> {
      ....
    void watch(K key);
	void watch(Collection<K> keys);
	void unwatch();
	void multi();
	void discard();
	List<Object> exec();
      ....
  }

1.1 错误示例

然而,它们是不能单独直接被调用的,Spring Data官网有句话说:

Redis provides support for transactions through the multi, exec, and discard commands. These operations are available on RedisTemplate. However, RedisTemplate is not guaranteed to execute all operations in the transaction with the same connection.

大概意思是直接单独调用的话,RedisTemplate是不会保证这些操作在一个连接内完成,

//错误示例
public void testRedisTx0() {
	template.multi();
	template.opsForValue().set("hxm", "9999");
	System.out.println(template.opsForValue().get("hxm"));
	List<Object> result = template.exec();//此处抛出异常
	System.out.println(result);
}
//此处会导致一个异常
org.springframework.dao.InvalidDataAccessApiUsageException: No ongoing transaction. Did you forget to call multi?

上面的错误实例执行到exec方法时,会抛出以上的异常,可以看出程序认为你还没有执行过multi操作,所以不能执行exec。这是因为这几个操作都不是在一个连接完成的。

1.2 正确使用姿势

RedisTemplate提供了一种正确的使用方式,那就是execute(SessionCallback session)方法:

<T> T execute(SessionCallback<T> session);

SessionCallback包含了一个回调函数execute(RedisOperations operations),在这个函数里实现以上的操作,就可以保证事务的正常使用。

	public void testRedisTx1() {
		List<Object> r = template.execute(new SessionCallback<List<Object>>() {

			@Override
			public List<Object> execute(RedisOperations operations) throws DataAccessException {
				operations.multi();
				operations.opsForValue().set("hxm", "9999");
                  //此处打印null,因为事务还没真正执行
				System.out.println(operations.opsForValue().get("hxm"));
				return operations.exec();
			}
		});
		
		System.out.println(r);
	}

我们可以看看这个execute(SessionCallback session)方法的内部实现机理,可以看到该方法中先把当前建立的连接绑定在当前的线程中,确保之后的redis操作可以在一个连接内进行,而redis操作过后,会把当前连接在线程中解绑,并且释放这个连接。

public <T> T execute(SessionCallback<T> session) {
	RedisConnectionFactory factory = getRequiredConnectionFactory();
	//绑定连接在当前线程,可实现下面execute方法内的redis操作保持在一个连接内完成
	RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
	try {
		return session.execute(this);
	} finally {
		RedisConnectionUtils.unbindConnection(factory);//把连接从当前线程中解绑、释放连接
	}
}

2、@Transactional的支持

另一种实现事务的是@Transactional注解,这种方法是把事务交由给spring事务管理器进行自动管理。使用这种方法之前,跟jdbc事务一样,要先注入事务管理器,如果工程中已经有配置了事务管理器,就可以复用这个事务管理器,不用另外进行配置。另外,需要注意的是,跟第一种事务操作方法不一样的地方就是RedisTemplate的setEnableTransactionSupport(boolean enableTransactionSupport)方法要set为true,此处贴出官方的配置框架:

@Configuration
@EnableTransactionManagement                                 
public class RedisTxContextConfiguration {

  @Bean
  public StringRedisTemplate redisTemplate() {
    StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
    // explicitly enable transaction support
    template.setEnableTransactionSupport(true);//此处必须设置为true,不然没法实现事务管理            
    return template;
  }

  @Bean
  public RedisConnectionFactory redisConnectionFactory() {
    // jedis || Lettuce
  }

  @Bean
  public PlatformTransactionManager transactionManager() throws SQLException {
    return new DataSourceTransactionManager(dataSource());   
  }

  @Bean
  public DataSource dataSource() throws SQLException {
    // ...
  }
}

这种方法的使用方法比较简单,就在要使用事务的方法注解@Transactional,这跟jdbc事务使用是一样的,这样就不用手工的执行multi、exec方法了,这些事务控制方法会由spring事务管理器自动完成。实例如下:

	@Transactional
	public void testRedisTx2() {

		template.opsForValue().set("hxm", "9999");
		System.out.println(template.opsForValue().get("hxm"));//此处打印为null

	}

然而,这种便利的使用方法有局限性,就是不支持只读操作,如果执行get之类的操作,将会返回null,所以使用的时候要多加注意!

3、两种方法的对比

3.1 execute(SessionCallback session)方法

  • 事务代码块的范围灵活可控
  • 支持读操作
  • 代码略显臃肿

3.2 @Transactional注解方法

  • 使用方便,代码比较优雅
  • 不够灵活,事务控制范围是整个方法
  • 不支持读操作

综合了以上的对比,两种方法各有优缺点,但个人更偏向于使用execute方法。如果使用@Transactional这种注解式方法,有个建议是初始化两个RedisTemplate,一个支持事务的,一个不支持事务的,即enableTransactionSupport一个设为true,一个设为false(默认是false)。不然,如果用支持事务的RedisTemplate来进行非事务性操作时,有些地方要注意,比如要手工的关闭连接等,不然是会踩坑的!因为我就是过来人!至于是什么坑,留作下回分解~

Spring Data Redis 实践 关于Spring Data Redis的简单应用以及1.7新特性Redis Repositories简介~ 阅读详情

相关推荐

Spring Data Redis详解(超详细版)

Spring Data Redis是一个功能强大且易于使用的Redis客户端库。它封装了Redis的底层操作,为开发者提供了更加简洁、易用的API,使得在Spring应用中集成和使用Redis变得更加方便。通过合理的配置和使用,开发者可以轻松地在Spring应用中实现高效的数据存储和访问。随着Redis的不断发展和完善,Spring Data Redis也将不断更新和升级,以支持更多的Redis特性和功能。

专业深耕,技术前沿 1102

【redis系列】springboot使用redis事务

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

Think_and_work的博客 4411

后端领域如何高效使用 Spring Data Redis

在当今的后端系统中,“快"是用户体验的生命线。想象一下,当你打开购物App查看商品详情时,如果页面加载需要3秒,你可能会直接关闭App——而这3秒中,有2.5秒可能都耗在数据库查询上。Redis 就像超市里的"快速取货区”,把常用商品(热点数据)放在最容易拿到的地方,让用户无需跑到仓库(数据库)就能快速获取。但 Redis 本身只是个"仓库",如何高效管理这个仓库?如何避免"拿错货"(数据不一致)、“货架坍塌”(缓存雪崩)、“仓库拥堵”(连接池耗尽)等问题?

AI架构全栈开发实战笔记 1132

springboot使用redis事务

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

justlpf的专栏 1270

解析 Spring Data Redis 在后端领域的事务处理

理解Redis原生事务特性及其局限性掌握Spring Data Redis对事务的抽象和增强学习如何在复杂业务场景中正确使用事务了解分布式环境下的事务处理挑战和解决方案本文范围涵盖从基础概念到高级应用的完整知识体系,包括但不限于:Redis事务命令、Spring事务抽象、@Transactional注解、事务传播行为、分布式锁与事务的结合使用等。首先介绍Redis原生事务特性和Spring Data Redis的基本概念然后深入分析事务处理的核心原理和实现机制。

欢迎来到我的优快云空间!这里聚焦AI大模型应用实战,分享前沿技术、实战案例与开发经验。 335

springboot-redis事务

springboot-redis事务

【Redis】Redis的事务碰上Spring的事务 @Transactional导致问题

建议大家去看原文,这里是学到了,记录一下。最近项目的生产环境遇到一个奇怪的问题:现象 :每天早上客服人员在后台创建客服事件时,都会创建失败。当我们重启 这个微服务后,后台就可以正常创建了客服事件了。到第二天早上又会创建失败,又得重启这个微服务才行。初步排查 :创建一个客服事件时,会用到 Redis 的递增操作来生成一个唯一的分布式 ID 作为事件 id。而恰巧每天早上这个递增操作都会返回 null,进而导致后面的一系列逻辑出错,保存客服事件失败。当重启微服务后,这个递增操作又正常了。

九师兄 637

从零配置到批量处理:FaceFusion 3.1完整使用指南(含hififace_256模型测试)

本文详细介绍了FaceFusion 3.1的完整使用指南,包括环境配置、模型选择(特别是hififace_256模型的深度测试)以及批量处理技巧。通过AI驱动的脸部替换技术,帮助用户高效实现高质量的面部处理,适用于影视制作、广告设计等多种场景。

weixin_29056865的博客 655

Spring Data Redis的基本使用

自用

jiabao0520的博客 1135

R语言安装包镜像报错?5分钟教你快速切换国内镜像源(含清华/阿里云配置)

本文详细介绍了R语言安装包镜像报错的解决方案,包括如何快速切换国内镜像源(如清华、阿里云等),解决'无法读写貯藏處索引'等常见问题。通过图形界面和命令行两种方式,帮助用户高效配置镜像源,提升R语言包安装速度与稳定性。

weixin_29053073的博客 418

知识图谱-Neo4j-开始构建知识图谱-01

关系(Relationships):连接两个节点,具有方向(→ 或 ←)和类型(Type),可附加属性。 属性(Properties):键值对,存储节点或关系的详细信息(如 , )。 (2) Cypher 查询语言 直观语法:通过模式匹配直接描述图结构。 高效遍历:支持复杂关系路径查询(如最短路径、模式匹配)。 3. 核心优势 (1) 原生图存储 物理存储优化:数据以图结构直接存储,避免传统数据库的“表连接”开销。 高效遍历:通过指针直接访问相邻节点,时间复杂度接近 O(1)。 (2) 高性

寓教于乐。教己助人 1万+

SpringBoot中使用redis事务

redis事务只支持单机,不支持cluster需要开启事务时,只需要在对应的方法或类上使用注解即可,SpringBoot自动开启了@EnableTransactionManagement需要注意事务不生效的几种情况redis事务依赖于jdbc的事务管理。

justlpf的专栏 2057

草莓成熟度与叶片病虫害智能检测数据集应用全解析

本文深入解析草莓成熟度与叶片病虫害智能检测数据集的应用价值,涵盖从绿草莓到红果转色的完整成熟周期及白粉病、炭疽病等7种病害的精准识别。通过实战案例展示如何提升病害识别率至94%,并介绍数据集的科研价值,包括跨品种迁移学习和多模态数据融合技术。

weixin_28366353的博客 274

Redis之坑:spring-data-redis中的Redis事务

Redis之坑:spring-data-redis中的Redis事务 Redis之坑:理解Redis事务 Redis之坑:Redis与MySQL中事务的区别 Transaction之坑:数据库事务 Transaction之坑:Spring中配置Transaction与不配置有何区别 Transaction之坑:分析sql执行结果,主动促使事务rollback SessionCall...

洛丹伦的夏天 9752

基于深度学习的停车位检测系统(UI界面 + YOLOv8/v7/v6/v5代码 + 训练数据集)

传统的停车位检测方法主要依赖于人工或基于简单图像处理的技术,存在检测速度慢、准确率低、环境适应性差等问题。近年来,随着深度学习技术的快速发展,基于目标检测的停车位检测系统已成为研究的热点。本文基于YOLO(You Only Look Once)系列模型(包括YOLOv5、YOLOv6、YOLOv7和YOLOv8),开发了一个完整的停车位检测系统,支持实时检测、结果可视化以及UI交互界面。本文实现了一个基于深度学习的停车位检测系统,采用YOLO模型在实时视频流中进行高效检测。

YOLO 332

【毕设护航】从0构建YOLOv8犬类识别系统,120种犬类精准检测+可视化界面全流程指南

本文介绍了一个基于YOLOv8的120种犬类目标检测与可视化系统毕业设计项目。该项目使用Stanford Dogs数据集,将图像分类任务转化为目标检测任务。主要内容包括:数据预处理(XML标注转换为YOLO格式)、YOLOv8模型训练与测试(包含训练脚本编写和推理实现),以及基于Tkinter的图形界面开发。该项目技术链条完整,涵盖检测、分割等多任务支持,适合作为计算机视觉方向的毕业设计选题,兼具技术深度和展示效果。

LXY_LOVE36的博客 96

Sping Data Redis 使用事务时,不关闭连接的问题

项目中使用到了Redis,最后决定用spring-data-redis来开发,配置好连接池,进入使用,似乎一切正常。  配置了两块redis,一个专门做读,一个专门做些, 配置的XML文件如下,这是一个专做写的redis配置: <bean id="connectionFactory" class="org.springframew

LiuHanFanShuang的博客 2万+

7、Python高光谱分析工具(PyHAT)简介

Python高光谱分析工具(PyHAT)是一个开源、跨平台的Python库及图形用户界面,用于行星光谱数据的可视化与分析。它支持多种高光谱传感器数据,如火星勘测轨道飞行器的CRISM、月船1号的M3以及SELENE Kaguya SP点光谱仪,提供预处理、衍生产品生成、统计学习和机器学习分析功能。PyHAT基于Pandas和NumPy构建,兼容Jupyter和QGIS环境,旨在解决现有光谱分析方法缺乏开源实现、难以探索性分析和算法分散的问题。其模块化架构涵盖数据输入/输出、通用光谱变换、测绘与点观测工具及高

aa123的博客 138

使用 Spring Data Redis 实现 Redis 数据存储详解

Spring Data Redis 是 Spring 生态中操作 Redis 的核心模块,它封装了 Redis 客户端的底层细节(如 Jedis 或 Lettuce),提供了统一的 API 来操作 Redis 的数据结构。确保所有操作的 Key/Value 序列化方式一致,避免出现乱码或类型错误。或手动关闭连接,避免未释放的连接耗尽资源。在 Redis 配置中设置。

FAQEW的博客 2861

漏洞挖掘之工具配置

本文主要讲解burp工具的插件安装。

qq_64775230的博客 3273

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

RedisTemplate 快速使用入门 与 操作 Redis 5 种数据类型、事务

目录 RedisTemplate 概述 与 redis 配置 RedisTemplate 使用演示 字符串(String) 列表(List) 哈希(Hash) 集合(Set) 有序集合(sorted set) RedisTemplate 概述 与 redis 配置 1、Redis 是一个缓存、消息代理和功能丰富的键值存储。Spring Boot 为 Lettuce 和 Jedis...

蚩尤后裔-汪茂雄 1万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Spring-data-redis介绍

spring data是用于简化数据库访问的开源框架,其主要目标是使得对数据的访问变得方便快捷,主要包括:jdbc、redis、jsp、elasticsearch只要是Java的开发,基本上都应用大型的开发环境(毕竟生态很成熟,别说所谓的其他语言好与坏),既然要开发啊Java项目,必然要有Spring开发框架,那么既然有了Spring开发框架,就需要"万物整合",自然也就包含了Redis的整合,

weixin_42486553的博客 1688

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Spring Data Redis 详解

Redis 其实非常简单,但是使用了 Spring Data Redis,会发现更简单,其实相当于加了个中间层在里面,并不需要再去关注多种 Redis 的工具库了。

RedRay0的博客 1995

Redis以及Spring Data Redis

springboot项目中资源缓存,以及定时清理无用资源

轻言细语莫泪痕 2014

使用Spring Data Redis操作Redis(一) 很全面

Spring-Data-Redis项目(简称SDR)对Redis的Key-Value数据存储操作提供了更高层次的抽象,类似于Spring Framework对JDBC支持一样。 项目主页: http://projects.spring.io/spring-data-redis/ 项目文档: http://docs.spring.io/spring-data/redis/docs/1.5

adsadadaddadasda的博客 4万+
上一篇: 为什么HotspotJVM垃圾回收中的“标记-复制”算法需要两个survivor空间?
下一篇: 带你用广度优先搜索实现地铁计费功能
H阿布
博客等级 码龄12年 24粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值