【SpringBoot】Redisson 分布式锁注解和 @Transactional 注解一起使用问题

一、前言

平时使用切面去加分布式锁,是先开启事务还是先尝试获得锁?这两者有啥区别?

业务中怎么控制切面的顺序?切面的顺序对事务的影响怎么避免?

下面程序分析:

    @Override@Transactionalpublic ReceiveH5ActivityPrizeResponse receive(ReceiveH5ActivityPrizeRequest request) {logger.info("xxx:{}", JSON.toJSONString(request));ReceiveH5ActivityPrizeResponse response=new ReceiveH5ActivityPrizeResponse();String lockName="receiveH5ActivityPrize" + request.getActivityId();final DistributeLock lock = jedisLockFactory.getJedisLock(lockName,20, TimeUnit.SECONDS);// 1.加锁lock.lock();try {//todo // 2 业务逻辑 先判断是否存在,不存在插入一条数据,存在返回(不插入)} finally {// 3.释放锁lock.unLock();}// 4 返回return response;}

分布式锁失效并不是真正的失效,只是读到数据,读取的数据库数据不是最新的。

@Transactional 注解在执行该方法时开启一个事物,当执行到3步时,insert 事物务还未提交,因此其它线程进入分布式锁代码块后,继续会执行2操作,发现数据不存在继续插入一条新数据,存在两条记录,此时数据就会出现 bug 问题。

解决办法:先加锁,然后在开启事物,可以保证安全性。 

二、普通未指定 order 的切面和 @Transactional 的先后顺序

        先说下为啥会考虑到这个,我们可以知道 @Transaction 一般加在具体要执行业务的service 方法上,那如果我要进行并发控制对业务进行加锁,那么尝试锁和开启事务孰先孰后呢?

    @Override@Transactional@RedisLock(key = Constant.FANLI_GRANT_VIP_LOCK, param = "#vipOrderNo")public void grantGdVip(String vipOrderNo) {// 业务逻辑}

        按照业务流程上来看我们需要先尝试锁后开启事务,因为没获得锁开启事务需要和数据库进行交互开启一个新的事务,平常对业务结果是不会影响的,但是当高并发时是会对数据库带来不小压力。

总结:

        如果普通切面没指定 order 会比 transaction 后执行。当锁或者一些检查性切面被使用时如果条件不满足不能进入业务也会导致事务的开启产生了不必要的消耗,当并发高时尤为明显。

三、切面的顺序对事务的影响怎么避免?

其实避免方式有三种,一种是指定order,一种是把自定义切面移到更外层中,一种是使用编程式事务。

1、指定 Order

@Aspect
@Component
@Slf4j
@Order(1)
public class LockAspect {}

2、移到最外层中

移到更外层中就不用证明了,调用的自然顺序,比如放在Controller的方法上。

    @PostMapping("/web/cardb/gift/receive")@ApiOperation("B卡赠品领取接口")@TokenAuthentication@RedisLock(key = LockKey.RECEIVE_CARD_B_GIFT, param = "#userInfo.userId")public ApiResultResponse receiveCardBGift(@RequestBody @Valid CardbReceiveGiftRequest request) {// 代码
}

3、使用编程式事务

 当然可以,调用的自然顺序,事务的开启更加现式。

四、总结

因为声明式事务比较好用,生产中使用的比较多,只有为了控制事务粒度或者不需要抽出一个新的类(为了使事务生效)才会使用编程式事务。

所以更加倾向于移到更外层,因为指定 order 的前提是你知道事务切面的和不指定order普通切面的顺序,同时一旦切面变多比如有统一加锁切面、统一检查是否认证切面等需要控制自定义切面顺序容易和事务切面搞混,不利于维护,这个也相当于自定义切面和框架前面隔离。这也从一个侧面证明了校验放 controller 的合理性。

五、参考文档

@Transactional和普通自定义切面执行顺序的思考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/162822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uni-app - 弹出框

目录 1.基本介绍 2.原生uinapp 通过uni.showActionSheet实现 3.使用组件 Popup 弹出层 ③效果展示 1.基本介绍 弹出框让我们在需要时在屏幕底部弹出一个菜单,它通常用于在各种应用程序中进行选择操作。Uniapp为我们提供了基本的底部弹出框组件,但它也有…

OpenSearch开发环境安装Docker和Docker-Compose两种方式

文章目录 简介常用请求创建映射写入数据查询数据其他 安装Docker方式安装OpenSearch安装OpenSearchDashboard Docker-Compose方式Docker-Compose安装1.设置主机环境2.下载docker-compose.yml文件3.启动docker-compose4.验证 问题问题1:IPv4 forwarding is disabled.…

如何搭建Zblog网站并通过内网穿透将个人博客发布到公网

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员,自己搭建网站制作网页是绕…

Altium Designer学习笔记11

画一个LED的封装: 使用这个SMD5050的封装。 我们先看下这个芯片的功能说明: 5050贴片式发光二极管: XL-5050 是单线传输的三通道LED驱动控制芯片,采用的是单极性归零码协议。 数据再生模块的功能,自动将级联输出的数…

CSGO搬砖干货,全网最详细教学!

CSGO游戏搬砖全套操作流程及注意事项(第一课) 在电竞游戏中,CSGO(Counter-Strike: Global Offensive)被广大玩家誉为经典之作。然而,除了在游戏中展现个人实力和团队合作外,有些玩家还将CSGO作为…

Java之API(上)

前言: 这一次内容主要是围绕Java开发中的一些常用类,然后主要是去学习这些类里面的方法。 一、高级API: (1)介绍:API指的是应用程序编程接口,API可以让编程变得更加方便简单。Java也提供了大量API供程序开发者使用&…

如何使用Google My Business来提升您的内容和SEO?

如果您的企业有实体店,那么使用Google My Business(GMB)来改善您的本地SEO并增强您的在线形象至关重要。Google My Business (GMB) 是 Google 提供的补充工具,使企业能够控制其在 Google 搜索和地图上的数字…

大数据基础设施搭建 - Flume

文章目录 一、上传压缩包二、解压压缩包三、监控本地文件(file to kafka)3.1 编写配置文件3.2 自定义拦截器3.2.1 开发拦截器jar包(1)创建maven项目(2)开发拦截器类(3)开发pom文件&a…

【数字化转型方法论读书笔记】-数据中台角色解读

一千个读者,就有一千个哈姆雷特。同样,数据中台对于企业内部不同角色的价值也不同,下面分别从董事长、CEO、 CTO/CIO、IT 架构师、数据分析师这 5 个角色的视角详细解读数据中台。 1、董事长视角下的数据中台 在数字经济时代,企业…

RTT打印在分区跳转后无法打印问题

场景: RTT打印仅占用JLINK的带宽,比串口传输更快更简洁,同时RTT可以使用jscope对代码里面的变量实时绘图显示波形,而采用串口打印波形无法实时打印。同时可以保存原始数据到本地进行分析,RTT在各方面完胜串口。 问题描…

PTA-城市间紧急救援

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的…

采样概率 假设检验推导数组最大值的方法与可行性

当需要寻找大量数据中的最大值的时候,比如从 2G 个 float16 中寻找其中的最大值,是一件耗时的操作。 现计划通过小样本来发掘数据的规律,对最大值进行预测。 方案: step1,从2G个float16 中截取64段float16&#xff…

【Vue入门篇】基础篇—Vue指令,Vue生命周期

🎊专栏【JavaSE】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【如愿】 🎄欢迎并且感谢大家指出小吉的问题🥰 文章目录 🍔Vue概述🎄快速入门🌺Vue指令⭐v-…

AI绘画工具汇总:免费、简单易上手

欢迎来到魔法宝库,传递AIGC的前沿知识,做有格调的分享❗ 喜欢的话记得点个关注吧! 提到AI绘画,许多人通常会想到Midjourney和Stable Diffusion等工具,然而,这些工具对于新手而言门槛较高,不太友…

【C++】——标准模板库STL作业(其一)

🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL&#xff1a…

opencv使用pyinstaller打包错误:‘can‘t find starting number (in the name of file)

使用Python语言和opencv模块在pycharm中编辑的代码运行没问题,但是在使用pyinstaller打包后出现错误can‘t find starting number (in the name of file) [ERROR:0] global C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-q3d_8t8e\opencv\modules\videoi…

安卓毕业设计基于安卓android微信小程序的家校通系统

运行环境 开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序运行软件:微信开发者 项目介绍 基于微信小程序的家校通系统的设计基…

【实用】PPT没几页内存很大怎么解决

PPT页数很少但导出内存很大解决方法 1.打开ppt点击左上角 “文件”—“选项” 2.对话框选择 “常规与保存” (1)如果想要文件特别小时可 取消勾选 “将字体嵌入文件” (2)文件大小适中 可选择第一个选项 “仅最入文档中所用的字…

每日一题 1410. HTML 实体解析器(中等,模拟)

模拟&#xff0c;没什么好说的 class Solution:def entityParser(self, text: str) -> str:entityMap {&quot;: ",&apos;: "",>: >,<: <,&frasl;: /,&amp;: &,}i 0n len(text)res []while i < n:isEntity Falseif …

Oracle-客户端连接报错ORA-12545问题

问题背景: 用户在客户端服务器通过sqlplus通过scan ip登陆访问数据库时&#xff0c;偶尔会出现连接报错ORA-12545: Connect failed because target host or object does not exist的情况。 问题分析&#xff1a; 首先&#xff0c;登陆到连接有问题的客户端数据库上&#xff0c;…