注解方式优雅的实现 Redisson 分布式锁
1前言
日常开发中,难免遇到一些并发的场景,为了保证接口执行的一致性,通常采用加锁的方式,因为服务是分布式部署模式,本地锁Reentrantlock和Synchnorized这些就先放到一边了,Redis的setnx锁存在无法抱保证原子性的问题就暂时搁且到一边,直接上大招Redisson也是我最近开发项目中基本都在用的缓存,并且也都是用它的分布式锁机制。
2Redisson分布式锁常规使用
关于Redisson的一些基本概念,本章就不做太详细的说明了,有兴趣的小伙伴可以自己去了解下,主要说下加锁的常规使用,Redisson分布式锁是基于Redis的Rlock锁,实现了JavaJUC包下的Lock接口。
Lock
public void getLock(){//获取锁RLock lock = redisson.getLock("Lxlxxx_Lock");try {// 2.加锁lock.lock();} catch (InterruptedException e) {e.getStackTrace();} finally {// 3.解锁lock.unlock();System.out.println("Finally,释放锁成功");}
getLock获取锁,lock.lock进行加锁,会出现的问题就是lock拿不到锁一直等待,会进入阻塞状态,显然这样是不好的。
TryLock
返回boolean类型,和Reentrantlock的tryLock是一个意思,尝试获取锁,获取到就返回true
RLock lock = redisson.getLock(name);
try {if (lock.tryLock(2, 10, TimeUnit.SECONDS)) {//执行业务逻辑} else {System.out.println("已存在");}
} catch (InterruptedException e) {e.printStackTrace();
}finally {
//判断当前线程持有的锁是不是处于锁定状态,锁定状态再进行释放if (this.redissonLock.isHeldByCurrentThread(lockName)) {this.redissonLock.unlock(lockName);}
}
3自定义注解实现锁机制
通常我们都会将redisson实例注入到方法类里面,然后调用加锁方法进行加锁,如果其他业务方法也需要加锁执行,将会产生很多重复代码,由此采用AOP切面的方式,只需要通过注解的方式就能将方法进行加锁处理。另外,搜索公众号Linux就该这样学后台回复“猴子”,获取一份惊喜礼包。
自定义注解
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DistributedLock {String key() default "";int leaseTime() default 10;boolean autoRelease() default true;String errorDesc() default "系统正常处理,请稍后提交";int waitTime() default 1;
}
切面类实现
@Aspect
@Component
public class DistributedLockHandler {private static final Logger log = LoggerFactory.getLogger(DistributedLockHandler.class);@AutowiredRedissonLock redissonLock;public DistributedLockHandler() {}@Around("@annotation(distributedLock)")public Object around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) throws Throwable {String lockName = this.getRedisKey(joinPoint, distributedLock);int leaseTime = distributedLock.leaseTime();String errorDesc = distributedLock.errorDesc();int waitTime = distributedLock.waitTime();Object var8;try {boolean lock = this.redissonLock.tryLock(lockName, (long)leaseTime, (long)waitTime);if (!lock) {throw new RuntimeException(errorDesc);}var8 = joinPoint.proceed();} catch (Throwable var12) {log.error("执行业务方法异常", var12);throw var12;} finally {if (this.redissonLock.isHeldByCurrentThread(lockName)) {this.redissonLock.unlock(lockName);}}return var8;}/*** 获取加锁的key* @param joinPoint* @param distributedLock* @return*/private String getRedisKey(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) {String key = distributedLock.key();Object[] parameterValues = joinPoint.getArgs();MethodSignature signature = (MethodSignature)joinPoint.getSignature();Method method = signature.getMethod();DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();String[] parameterNames = nameDiscoverer.getParameterNames(method);if (StringUtils.isEmpty(key)) {if (parameterNames != null && parameterNames.length > 0) {StringBuffer sb = new StringBuffer();int i = 0;for(int len = parameterNames.length; i < len; ++i) {sb.append(parameterNames[i]).append(" = ").append(parameterValues[i]);}key = sb.toString();} else {key = "redissionLock";}return key;} else {SpelExpressionParser parser = new SpelExpressionParser();Expression expression = parser.parseExpression(key);if (parameterNames != null && parameterNames.length != 0) {EvaluationContext evaluationContext = new StandardEvaluationContext();for(int i = 0; i < parameterNames.length; ++i) {evaluationContext.setVariable(parameterNames[i], parameterValues[i]);}try {Object expressionValue = expression.getValue(evaluationContext);return expressionValue != null && !"".equals(expressionValue.toString()) ? expressionValue.toString() : key;} catch (Exception var13) {return key;}} else {return key;}}}
}
具体使用

方法头加自定义注解,key参数代表需要加锁的key,errorDesc获取锁失败提示报错信息。
这边我将项目通过修改端口启动了两个服务,分别是8460和8461


通过postman调用这两个服务,模拟两个服务同时获取一把锁的场景,其中一个服务拿到锁,

可以看到端口8460服务先拿到锁,8461服务tryLock获取锁失败,实现了加锁逻辑


分布式锁的使用场景还是需要多注意下,根据业务场景来,并发量不大的情况下,其实没有
相关文章:
注解方式优雅的实现 Redisson 分布式锁
1前言 日常开发中,难免遇到一些并发的场景,为了保证接口执行的一致性,通常采用加锁的方式,因为服务是分布式部署模式,本地锁Reentrantlock和Synchnorized这些就先放到一边了,Redis的setnx锁存在无法抱保证…...
PHP/Laravel通过经纬度计算距离获取附近商家
实际开发中,常常需要获取用户附近的商家,思路是 获取用户位置(经纬度信息)在数据库中查询在距离范围内的商家 注: 本文章内计算距离所使用地球半径统一为 6378.138 km public function mpa_list($latitude,$longitude,$distance){// $latitude 34.306465;// $longitude 10…...
grafana面板介绍
grafana 快速使用 背景 随着公司业务的不断发展,紧接来的是业务种类的增加、服务器数量的增长、网络环境的越发复杂以及发布更加频繁,从而不可避免地带来了线上事故的增多,因此需要对服务器到应用的全方位监控,提前预警…...
实验三 循环结构程序设计(Python)
第1关:打印图形 zm=input("") #代码开始#代码结束def print_pattern(letter):if not letter.isalpha() or not letter.isupper():print("请输入大写字母")returnstart_char = Aend_char = letterfor i in range(ord(start_char), ord(end_char) + 1):spa…...
Flutter笔记:目录与文件存储以及在Flutter中的使用(上)
Flutter笔记 目录与文件存储以及在Flutter中的使用(上) 文件系统基础知识与路径操作 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:h…...
注意了!申请流量卡时地址一定不要填写学校,不好下卡哦!
当我们在网上购买流量卡时,都会要求让填写准确的收货地址,但是对于收货地址你填对了吗? 很多朋友在提交流量卡申请之后,往往会被运营商拒审,对于拒审的原因除了比较常见的信息填写有有误、涉及禁发地区、重复申…...
minio使用shell上传文件
minio使用shell上传文件 前言1. 编写调用脚本2.测试脚本上传3.候选脚本 前言 业务场景需要实现,服务器文件上传至存储服务。一种方式是安装minio的linux客户端,另一种方式是通过调用minio的api接口实现文件上传。后一种方式不需要依赖minio的客户端使用…...
LeetCode538. Convert BST to Greater Tree
文章目录 一、题目二、题解 一、题目 Given the root of a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus the sum of all keys greater than the original key in BST. As a remin…...
iPaaS和RPA,企业自动化应该如何选择?
全球著名的咨询调查机构Gartner在2022年初再次发布了《2022年12大技术趋势》报告。 Gartner是全球最具权威的IT研究与顾问咨询公司,成立于1979年,在界定及分析那些决定了商业进程的发展趋势与技术方面,它拥有二十年以上的丰富经验,…...
AI实践与学习1_Milvus向量数据库实践与原理分析
前言 随着NLP预训练模型(大模型)以及多模态研究领域的发展,向量数据库被使用的越来越多。 在XOP亿级题库业务背景下,对于试题召回搜索单单靠着ES集群已经出现性能瓶颈,因此需要预研其他技术方案提高试题搜索召回率。…...
3Dexcite deltgen 2022x 新功能
3DEXCITE DELTAGEN 2022x 现已发布,此次新版发布包含 DELTAGEN 2022x,DELTAGEN MARKETING SUITE 2022x,DELTAGEN XPLORE 2022x,以及软件开发工具包 SDK FOR DELTAGEN 2022x 版本。赶快来获取最新 DG 版本,了解新增内容…...
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形 文章链接:柱状图中最大的矩形 视频链接:柱状图中最大的矩形 1. LeetCode 84. 柱状图中最大的矩形 1.1 思路 本题是给一个数组形象得画出图后求矩形的最大面积是多少。本题和42. 接雨水…...
【2023云栖】陈守元:阿里云开源大数据产品年度发布
本文根据 2023 云栖大会演讲实录整理而成,演讲信息如下: 演讲人:陈守元 | 阿里云计算平台事业部开源大数据产品总监 演讲主题:阿里云开源大数据产品年度发布 随着云计算的不断发展,未来数据处理和应用的趋势将围绕C…...
Element UI 禁用数字输入框组件添加鼠标滚动事件
Element UI 禁用数字输入框组件添加鼠标滚动事件 <el-input type"number" mousewheel.native.prevent DOMMouseScroll.native.prevent :min"0" onkeyup"this.valuethis.value.match(/\d\.?\d{0,2}/);"v-model"form.threeYearDevelop…...
担忧CentOS停服?KeyarchOS系统来支撑
担忧CentOS停服?KeyarchOS系统来支撑 近年发生的“微软黑屏门”、“微软操作系统停更”等安全事件,敲响了我国 IT 产业的警钟,建立由我国主导的 IT 产业生态尤为迫切。对此,我国信息技术应用创新行业乘势而起,旨在通过…...
聚观早报 |联想集团Q2财季业绩;小鹏汽车Q3营收
【聚观365】11月17日消息 联想集团Q2财季业绩 小鹏汽车Q3营收 微软发布两款自研AI芯片 FAA批准SpaceX再次发射星际飞船 2023 OPPO开发者大会 联想集团Q2财季业绩 全球数字经济领导企业联想集团公布截至2023年9月30日的2023/24财年第二财季业绩:整体营收达到10…...
SAP ABAP权限控制中常用TCODE
权限控制中的几个TCODE 1.创建新的权限对象并在程序中使用 利用SU21创建权限对象Z_TEST,在程序中检查授权。 检查的代码如下: AUTHORITY-CHECK OBJECT ‘Z_TEST’ID ‘ACTION’ FIELD ‘44′ID ‘BUKRS’ FIELD DUMMY .IF sy-subrc NE 0.MESSAGE e00…...
云计算赛项容器云2023搭建
部署容器云平台[5 分] 使 用 OpenStack 私 有 云 平 台 创 建 两 台 云 主 机 , 云 主 机 类 型 使 用 4vCPU/12G/100G 类型,分别作为 Kubernetes 集群的 Master 节点和 node 节点, 然后完成 Kubernetes 集群的部署,并完成 Istio …...
11.1 文件拷贝移动与删除
在编程中,针对磁盘与目录的操作也是非常重要的,本章将重点介绍如何实现针对文件目录与磁盘的操作方法,其中包括了删除文件,文件拷贝,文件读写,目录遍历输出,遍历磁盘容量信息,磁盘格…...
redhat下使用CentOS yum源,并安装docker
一、安装yum源 1.卸载yum # 查看系统自身安装的yum软件包 rpm -qa | grep yum # 卸载软yum件包 rpm -e 软件包名称 --nodeps #可以使用简称如 rpm -e yum-* --nodeps2. 安装yum [rootbogon ~]# rpm -ivh --nodeps https://mirrors.aliyun.com/centos/8/BaseOS/x86_64/os/Pa…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
