分布式锁框架Lock4j简单使用

最近项目中使用到了Lock4j的分布式锁组件,小编今天就带大家学习一下该框架,以及如何在我们项目中进行集成使用。

一、简介

Lock4j是一个分布式锁组件,它提供了多种不同的支持以满足不同性能和环境的需求;它基于Spring AOP,支持RedisTemplateRedissonZookeeper作为底层。

二、开源地址

https://gitee.com/baomidou/lock4j

Lock4j框架源码目录结构

关于具体实现源码分析,小编这里就不带大家介绍了~

三、特性

  • 简单易用,功能强大,扩展性强。

  • 支持redissionredisTemplatezookeeper。可混用,支持扩展。

四、Lock4j注解介绍

@Lock4j注解共有六个属性:

属性说明
name需要锁住的key名称
executorlock 执行器,可以使用该参数自定义设置
keys需要锁住的keys名称,可以是多个
expire锁过期时间,主要是用来防止死锁
acquireTimeout可以理解为排队等待时长,超过这个时长就退出排队,并排除获取锁超时异常
autoRelease是否自动释放锁,默认为true
public @interface Lock4j {/*** 用于多个方法锁同一把锁 可以理解为锁资源名称 为空则会使用 包名+类名+方法名** @return 名称*/String name() default "";/*** @return lock 执行器*/Class<? extends LockExecutor> executor() default LockExecutor.class;/*** support SPEL expresion 锁的key = name + keys** @return KEY*/String[] keys() default "";/*** @return 过期时间 单位:毫秒* <pre>*     过期时间一定是要长于业务的执行时间. 未设置则为默认时间30秒 默认值:{@link Lock4jProperties#expire}* </pre>*/long expire() default -1;/*** @return 获取锁超时时间 单位:毫秒* <pre>*     结合业务,建议该时间不宜设置过长,特别在并发高的情况下. 未设置则为默认时间3秒 默认值:{@link Lock4jProperties#acquireTimeout}* </pre>*/long acquireTimeout() default -1;/*** 业务方法执行完后(方法内抛异常也算执行完)自动释放锁,如果为false,锁将不会自动释放直至到达过期时间才释放 {@link com.baomidou.lock.annotation.Lock4j#expire()}** @return 是否自动释放锁*/boolean autoRelease() default true;}

五、简单使用

5.1、引入相关依赖

pom.xml

<!-- 引入Lock4j依赖 -->
<!-- 若使用redisTemplate作为分布式锁底层,则需要引入 -->
<dependency><groupId>com.baomidou</groupId><artifactId>lock4j-redis-template-spring-boot-starter</artifactId><version>2.2.4</version>
</dependency>
<!-- 若使用redisson作为分布式锁底层,则需要引入 -->
<dependency><groupId>com.baomidou</groupId><artifactId>lock4j-redisson-spring-boot-starter</artifactId><version>2.2.4</version>
</dependency>

5.2、添加redis相关配置

application.yml

spring:redis:database: 1# Redis服务器地址 写你的iphost: 127.0.0.1# Redis服务器连接端口port: 6379# Redis服务器连接密码(默认为空)password:# 连接池最大连接数(使用负值表示没有限制  类似于mysql的连接池jedis:pool:max-active: 200# 连接池最大阻塞等待时间(使用负值表示没有限制) 表示连接池的链接拿完了 现在去申请需要等待的时间max-wait: -1# 连接池中的最大空闲连接max-idle: 10# 连接池中的最小空闲连接min-idle: 0# 连接超时时间(毫秒) 去链接redis服务端timeout: 6000

5.3、简单使用

LockController.java

@RestController
@RequestMapping("/lock")
public class LockController {@Autowiredprivate LockService lockService;/*** @param key* @return*/@GetMapping@Lock4j(keys = {"#key"}, acquireTimeout = 1000, expire = 6000)@SneakyThrowspublic R testLock(@RequestParam String key) {Thread.sleep(3000);return R.success(key);}
}

浏览器地址栏访问:http://localhost:8080/lock?key=xxkfz

{"code":200,"status":true,"message":"xxkfz","data":null}

我们在浏览器连续快速访问上述地址,模拟抢占不到锁得场景:

抢占不到锁的情况默认将会抛出:com.baomidou.lock.exception.LockFailureException: request failed,please retry it.异常。

如下图所示:

默认的锁获取失败策略为 com.baomidou.lock.DefaultLockFailureStrategy.

我们也可以自己定义抢占锁失败执行策略:

我们只需要创建一个类实现LockFailureStrategy接口重写onLockFailure方法即可。

CustomLockFailureStrategy.java

@Component
@Slf4j
public class CustomLockFailureStrategy implements LockFailureStrategy {/*** 锁失败事件** @param key* @param method* @param arguments*/@Overridepublic void onLockFailure(String key, Method method, Object[] arguments) {log.error("抢占锁失败:{}==={}", key, method.getName());}
}

此时,抢占锁失败将会输出以下日志:

2023-12-03T15:13:33.455+08:00 ERROR 18952 --- [nio-8080-exec-3] c.x.s.config.CustomLockFailureStrategy   : 抢占锁失败:lock4j:com.xxkfz.simplememory.controller.LockControllertestLock#xxkfz===testLock
2023-12-03T15:13:38.468+08:00 ERROR 18952 --- [nio-8080-exec-4] c.x.s.config.CustomLockFailureStrategy   : 抢占锁失败:lock4j:com.xxkfz.simplememory.controller.LockControllertestLock#xxkfz===testLock

六、高级使用

6.1、自定义执行器

创建类CustomRedissonLockExecutor.java继承抽象类AbstractLockExecutor,通过源码可以得知,AbstractLockExecutor抽象类实现了LockExecutor接口,我们重写acquirereleaseLock方法即可。

CustomRedissonLockExecutor.java

@Component
public class CustomRedissonLockExecutor extends AbstractLockExecutor {/*** 加锁** @param lockKey        锁标识* @param lockValue      锁值* @param expire         锁有效时间* @param acquireTimeout 获取锁超时时间* @return 锁信息*/@Overridepublic Object acquire(String lockKey, String lockValue, long expire, long acquireTimeout) {return null;}/*** 解锁** <pre>* 为何解锁需要校验lockValue* 客户端A加锁,一段时间之后客户端A解锁,在执行releaseLock之前,锁突然过期了。* 此时客户端B尝试加锁成功,然后客户端A再执行releaseLock方法,则将客户端B的锁给解除了。* </pre>** @param key          加锁key* @param value        加锁value* @param lockInstance 锁实例* @return 是否释放成功*/@Overridepublic boolean releaseLock(String key, String value, Object lockInstance) {return false;}
}

6.2、自定义锁key生成器

默认的锁key生成器为 com.baomidou.lock.DefaultLockKeyBuilder ,我们创建类CustomKeyBuilder继承DefaultLockKeyBuilder重写buildKey方法,自己实现key生成逻辑即可。

CustomKeyBuilder.java

@Component
@Slf4j
public class CustomKeyBuilder extends DefaultLockKeyBuilder {public CustomKeyBuilder(BeanFactory beanFactory) {super(beanFactory);}@Overridepublic String buildKey(MethodInvocation invocation, String[] definitionKeys) {return super.buildKey(invocation, definitionKeys);}
}

6.3、手动上锁解锁

LockService.java

@Service
public class LockService {@Autowiredprivate LockTemplate lockTemplate;public void lock(String key) {// 获取锁LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class);if (Objects.isNull(lockInfo)) {throw new RuntimeException("业务处理中,请稍后再试......");}// 获取锁成功,处理业务try {// 处理业务逻辑 } catch (Exception e) {throw new RuntimeException(e);} finally {//释放锁lockTemplate.releaseLock(lockInfo);}}
}

分布式锁框架Lock4j简单使用

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

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

相关文章

YOLOv7+姿态估计Pose+tensort部署加速

YOLOv7-Pose YOLOv7是一种高效的目标检测算法&#xff0c;用于实时物体检测。姿态估计Pose是一种用于识别和跟踪人体关键点的技术。TensorRT是一个针对深度学习推理任务进行加速的高性能推理引擎。 将YOLOv7和姿态估计Pose与TensorRT结合可以实现快速而准确的目标检测和姿态估…

SSM框架(五):Maven进阶

文章目录 一、分模块开发1.1 分模块开发的意义1.2 步骤 二、依赖管理2.1 依赖传递2.2 可选依赖和排除依赖 三、继承与聚合3.1 聚合3.2 继承3.3 聚合和继承区别 四、属性4.1 pom文件的依赖使用属性4.2 资源文件使用属性 五、多环境开发六、跳过测试七、私服7.1 下载与使用7.2 私…

IDEA2022 Git 回滚及回滚内容恢复

IDEA2022 Git 回滚 ①选择要回滚的地方&#xff0c;右键选择 ②选择要回滚的模式 ③开始回滚 ④soft模式回滚的内容会保留在暂存区 ⑤输入git push -f &#xff0c;然后重新提交&#xff0c;即可同步远程 注意观察IDEA右下角分支的标记&#xff0c;蓝色代表远程内容未同步到本…

Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

学习视频&#xff1a;孙哥说SpringMVC&#xff1a;结合Thymeleaf&#xff0c;重塑你的MVC世界&#xff01;&#xff5c;前所未有的Web开发探索之旅 第三章、SpringMVC控制器开发详解 3.1 核心要点 &#x1f4a1; 1. 接受客户端&#xff08;client&#xff09;请求参数[讲解] 2…

vue+less+style-resources-loader 配置全局颜色变量

全局统一样式后&#xff0c;可配置vue.config.js实现全局颜色变量&#xff0c;方便在编写时使用统一风格的色彩 一、新建global.less 二、下载安装style-resources-loader npm i style-resources-loader --save-dev三、在vue.config.js中进行配置 module.exports {pluginOpt…

二. BEV感知算法基础模块讲解

目录 前言0. 简述1. 基础模块补充讲解1.1 2D图像处理1.2 3D特征之点处理方案1.3 3D特征之体素处理方案 2. 从2D到3D转换模块2.1 LSS(Lift,Splat and Shoot)2.2 Pseudo LiDAR 3. 从3D到2D转换模块3.1 Explicit Mapping3.2 Implicit Mapping 4. BEV感知中的Transformer4.1 空间注…

正是阶段高等数学复习--函数极限的计算

之前在预备阶段中函数极限的解决方式分三步&#xff0c;第一步观察形式并确定用什么方式来解决&#xff0c;第二步化简&#xff0c;化简方式一共有7种&#xff0c;分别是最重要的三种&#xff08;等价替换、拆分极限存在的项、计算非零因子&#xff09;以及次重要的4种&#xf…

教你一招,轻松搭建dns域名服务器

目录 一、DNS简介二、安装DNS 一、DNS简介 域名系统&#xff08;DNS&#xff09;是一个分层的分布式数据库。它存储用于将Internet主机名映射到IP地址&#xff08;反之亦然&#xff09;的信息、邮件路由信息以及Internet应用程序使用的其他数据。 客户端通过调用解析器库在DNS…

高端制造业中的通用性超精密3D光学测量仪器

超精密光学3D测量仪器具有高精度、自动化程度高、实时反馈和范围广等优势。它能够实现微米级别的精确测量&#xff0c;能够精确测量产品的尺寸、形状和表面粗糙度等&#xff0c;具有广泛的应用价值和重要意义。 超精密光学3D测量仪器配备多种传感器、控制器和计算机系统&#…

Java(十)(网络编程,UDP,TCP)

目录 网络编程 两种软件架构 网络通信的三要素 IP IPv4的地址分类 特殊IP 端口号 协议 用UDP协议发送数据 用UDP接收数据 TCP接收和发送数据 TCP通信--支持与多个客户端同时通信 网络编程 可以让设备中的程序与网络上其他设备的程序进行数据交互(实现网络通信) 两…

go自定义端口监听停用-------解决端口被占用的问题

代码 package mainimport ("fmt""log""net""os/exec""strconv""strings" )func getSelect(beign int, end int) int {var num intfor {_, err : fmt.Scan(&num)if err ! nil {fmt.Println("输入错误&am…

redis实现消息延迟队列

业务场景 在很多软件系统功能中都会出现定时任务的业务场景,比如提前点单,比如定时发布动态,文章等而出现这样的的定时的任务为延迟队任务 代码模块 任务的持久化一般都需要建立一个任务表和任务日志表,避免宕机导致任务失效,先新建立一个数据库,创建基本的任务表和任务日志表…

字符串冲刺题

关卡名 字符串冲刺题 我会了✔️ 内容 1.掌握最长公共前缀问题 ✔️ 2.掌握字符串压缩问题 ✔️ 3.如果想挑战一下就研究&#xff1a;表示数值的字符串 ✔️ 1 最长公共前缀 这是一道经典的字符串问题&#xff0c;LeetCode14 先看题目要求&#xff1a;编写一个函数来查找…

28.线段树与树状数组基础

一、线段树 1.区间问题 线段树是一种在算法竞赛中常用来维护区间的数据结构。它思想非常简单&#xff0c;就是借助二叉树的结构进行分治&#xff0c;但它的功能却非常强大&#xff0c;因此在很多类型的题目中都有它的变种&#xff0c;很多题目都需要以线段树为基础进行发展。…

git报错invalid object xxx和unable to read tree xxxxxx

电脑出问题了&#xff0c;导致git仓库像是被损坏了一样&#xff0c;执行git status就会报错unable to read ree&#xff0c;无法正常提交代码至仓库&#xff0c;原因是本地代码仓库.git文件损坏了&#xff0c;无法找到正确的提交历史和路径。 找到了一个解决办法&#xff1a; …

数学字体 Mathematical fonts

Mathematical fonts 数学字体&#xff1a; ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ \\ \mathcal{ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ} \\ \mathfrak{ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ} \\ \mathbb{ABC…

geemap学习笔记015:下载哨兵2号(Sentinel-2)数据

前言 使用GEE下载数据应该是最常见的功能了&#xff0c;今天就介绍一下如何使用geemap下载哨兵2号(Sentinel-2)数据&#xff0c;分别包括自己画感兴趣&#xff0c;以及利用Assets中的shp文件进行下载。 1 自己画感兴趣下载哨兵2号影像 import geemap import eeMap geemap.M…

MQ - 消息系统

消息系统 1、消息系统的演变 在大型系统中&#xff0c;会需要和很多子系统做交互&#xff0c;也需要消息传递&#xff0c;在诸如此类系统中&#xff0c;你会找到源系统&#xff08;消息发送方&#xff09;和 目的系统&#xff08;消息接收方&#xff09;。为了在这样的消息系…

了解ThreadLocal的原理吗

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

YOLOv5改进 | 添加ECA注意力机制 + 更换主干网络之ShuffleNetV2

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本文给大家介绍一种轻量化部署改进方式&#xff0c;即在主干网络中添加ECA注意力机制和更换主干网络之ShuffleNetV2&#xff0c;希望大家学习之后&#xff0c;能够彻底理解其改进流程及方法~&#xff01;&#x1f308; 目…