分布式锁框架Lock4j简单使用

news2025/9/20 5:20:39

最近项目中使用到了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服务器地址 写你的ip
    host: 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 {

    @Autowired
    private LockService lockService;

    /**
     * @param key
     * @return
     */
    @GetMapping
    @Lock4j(keys = {"#key"}, acquireTimeout = 1000, expire = 6000)
    @SneakyThrows
    public 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
     */
    @Override
    public 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 锁信息
     */
    @Override
    public 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 是否释放成功
     */
    @Override
    public 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);
    }

    @Override
    public String buildKey(MethodInvocation invocation, String[] definitionKeys) {
        return super.buildKey(invocation, definitionKeys);
    }
}

6.3、手动上锁解锁

LockService.java

@Service
public class LockService {
    
    @Autowired
    private 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.coloradmin.cn/o/1282554.html

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

相关文章

HT4822 无输出隔直电容 立体声耳机放大器 中文资料

HT4822是一款无需输出隔直电容的立体声耳机放大器。HT4822支持差分和单端的模拟信号输入。 HT4822在3.6V供电下&#xff0c;THDN 1%&#xff0c;32ohm负载时能提供80mW的输出。其具有低至0.007%的THDN。HT4822能在2.5V-6.0V电源条件下工作&#xff0c;具有过热保护和欠压保护等…

网站变成灰色,实现方式

微信公众号看到一片关于&#xff1a;设置网站变灰的实现方式&#xff0c;觉得很nice&#xff0c;亲测有效&#xff0c;记录一下代码。 https://mp.weixin.qq.com/s/m946vpRpEDFzJNuWRQJrpg方法一&#xff1a; <style type"text/css"> html {filter:grayscale…

练习11-简单卷积器的设计

简单卷积器的设计 1&#xff0c;任务目的&#xff1a;2&#xff0c;明确设计任务2.1,目前这部分代码两个文件没找到&#xff0c;见第5、6节&#xff0c;待解决中。 &#xff0c;卷积器的设计&#xff0c;RTL&#xff1a;con1.v4&#xff0c;前仿真和后仿真&#xff0c;测试信号…

回归分析:预测和建模

回归分析:预测和建模 写在开头1. 回归分析的基本概念2. 回归分析的方法2.1 简单线性回归2.1.1 数学知识2.1.2 应用举例2.2 多元线性回归2.2.1 数学公式和应用2.2.1 应用场景举例2.3 多项式回归2.3.1 数学公式和应用2.3.2 应用场景举例2.4 逻辑回归2.4.1 数学公式和应用2.4.2 应…

如何使用3D模型格式转换工具HOOPS Exchange访问PMI?

HOOPS Exchange允许您从CAD文件访问的一类重要信息是附加到 3D 模型的产品制造信息 (PMI)。PMI 详细说明了模型制造时应遵循的公差。过去&#xff0c;此信息称为几何尺寸和公差 (GD&T)&#xff0c;通常在与模型关联的单独图纸中维护。 制造信息与模型的分离意味着制造信息…

速达软件全系产品任意文件上传漏洞复现 [附POC]

文章目录 速达软件全系产品任意文件上传漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 速达软件全系产品任意文件上传漏洞复现 [附POC] 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技…

SWD和JTAG

1、调试接口概念 1&#xff09;SWD&#xff1a;Serial Wire Debug&#xff0c;代表串行线调试&#xff0c;是ARM设计的协议&#xff0c;用于对其微控制器进行编程和调试。 SWD 引脚&#xff1a; SWDIO–串行数据线&#xff0c;用于数据的读出和写入SWDCLK–串行时钟线&#…

3_企业级Nginx使用-day2

企业级Nginx使用-day2 学习目标和内容 1、能够编译安装并使用第三方模块 2、能够理解location语法的作用 3、能够了解URL的rewrite重写规则 4、能够理解防盗链原理和实现 一、第三方模块使用 Nginx官方没有的功能&#xff0c;开源开发者定制开发一些功能&#xff0c;把代码公…

142873-41-4脂质过氧化抑制剂1-星戈瑞

142873-41-4脂质过氧化抑制剂1 英文名称&#xff1a;Lipid peroxidation inhibitor 1 中文名称&#xff1a;脂质过氧化抑制剂 化学名称&#xff1a;2,4,6,7-四甲基-2-[(4-苯基哌啶-1-基)甲基]-3H-1-苯并呋喃-5-胺 CAS&#xff1a;142873-41-4 外观&#xff1a;固体粉末 分…

关于开展人工智能专业人员“自然语言及语音处理设计开发工程师”专项培训的通知

“人工智能技术与咨询”发布 工业与信息化部电子工业标准化研究院于2022年7月1日发布《人工智能从业技术人员要求》&#xff0c;现针对已发布标准于1月3日至7日在北京举办《自然语言与语音处理设计开发工程师》中级人才培养&#xff0c;下边是具体文件通知请大家查阅。行业人才…

物料 xx 未对销售组织 分销渠道 xx 语言 ZH 定义

查看具体 发现销售视图未维护&#xff0c;库存地点也未维护 即对应的MVKE ,MARD 都没有相关记录&#xff0c; 使得创建销售订单不成功。 解决方案 维护物料视图 mm50 然后选择对应的视图&#xff0c;再点击维护物料&#xff0c;进入到维护物料的视图里面 &#xff0c;填写…

基于Arduino的音乐喷泉设计(论文+源码)

1.系统设计 整个Audio Visualizer系统通过锂电池电源进行供电&#xff0c;当Arduino控制板通过蓝牙音频接收器模块与手机蓝牙完成匹配后&#xff0c;然后通过蓝牙音频接收器模块接收来自手机的音乐&#xff0c;接着通过对音乐进行FFT变换来得到音乐的频率数据&#xff0c;接着…

每日汇评:黄金触及2150美元区域附近的历史新高!

金价回落至2100美元以下&#xff0c;巩固了金价升至2144美元的历史新高的势头&#xff1b; 地缘政治紧张局势再起、美联储降息押注以及流动性不足引发金价大幅上涨&#xff1b; 在日线图上RSI指数超买的情况下&#xff0c;金叉形态仍在发挥作用&#xff1b; 金价最近的飙升可以…

工业机器视觉megauging(向光有光)使用说明书(十二,轻量级的visionpro)

关于最后一个工具的介绍&#xff1a;就是这个“相机图像” 我们可以鼠标双击点进去看一看&#xff1a; 在图像上点击&#xff0c;就可以截取一块图像&#xff0c;是可以放大缩小的&#xff0c;这个放大很low&#xff0c;是我以前研究缩放入门时的版本&#xff0c;本想删除&…

Vue练习 v-model 指令在状态和表单输入之间创建双向绑定

效果&#xff1a; <template><h2>Text Input</h2><input v-model"text"> {{ text }}<h2>Checkbox</h2><input type"checkbox" id"checkbox" v-model"checked"><label for"checkbox…

使用 .NET Upgrade Assistant(升级助手)升级 .NET 老旧版本项目

使用 .NET Upgrade Assistant 升级 .NET 老旧版本项目 .NET Upgrade Assistant 概述.NET Upgrade Assistant 功能1、支持以下代码语言&#xff1a;2、支持的 .NET 升级路径&#xff1a;3、支持的项目类型&#xff1a; .NET Upgrade Assistant 安装1、使用 Visual Studio 扩展安…

《我想假如在这里度过大学生活》火了,不愧是四川最美校园

近日&#xff0c;网上一篇关于成都理工大学校园环境的《我想假如在这里度过大学生活》火了。文章中的提到的大学环境优美&#xff0c;诗意盎然。一则则假如&#xff0c;带我们领略了校园的自然之美&#xff0c;发展之美、同时也感受到了大学时代的美好。 美丽的图书馆、阳光明媚…

想要备考PMP?PMP培训机构怎么选?

PMP是由项目管理协会&#xff08;Project Management Institute&#xff0c;简称PMI&#xff09;发起的项目管理专业人士资格认证&#xff0c;严格评估项目管理人员知识技能是否具有高品质的资格认证考试。作为近几年热门的证书&#xff0c;我国PMP备考人数和持证人数不断上升。…

【源码篇】基于SpringBoot+thymeleaf实现的蓝天幼儿园管理系统

基于SpringBootthymeleaf实现的蓝天幼儿园管理系统 文章目录 系统说明技术选型成果展示账号地址及其他说明 系统说明 基于SpringBootthymeleaf实现的蓝天幼儿园管理系统是为幼儿园提供的一套管理平台&#xff0c;可以提高幼儿园信息管理的准确性&#xff0c;系统将信息准确无误…

红队攻防之隐匿真实IP

0x01 前言 安全态势日益严峻&#xff0c;各大组织普遍采用了综合的安全产品&#xff0c;如态势感知系统、WAF和硬件防火墙等&#xff0c;这些措施加大了渗透测试和攻防演练的难度。即使是一些基本的漏洞验证、端口扫描&#xff0c;也可能导致测试IP被限制&#xff0c;从而阻碍…