分布式锁框架Lock4j简单使用

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 最近项目中使用到了Lock4j的分布式锁组件,小编今天就带大家学习一下该框架,以及如何在我们项目中进行集成使用。

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

一、简介

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

二、开源地址

https://gitee.com/baomidou/lock4j

image.png

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

三、特性

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

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

四、Lock4j注解介绍

@Lock4j注解共有六个属性:

属性 说明
name 需要锁住的key名称
executor lock 执行器,可以使用该参数自定义设置
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.异常。

如下图所示:

image.png

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

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

image.png

我们只需要创建一个类实现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简单使用

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
16天前
|
存储 人工智能 PyTorch
基于PyTorch/XLA的高效分布式训练框架
基于PyTorch/XLA的高效分布式训练框架
26 2
|
1月前
|
人工智能 算法 PyTorch
TorchAcc:基于 TorchXLA 的分布式训练框架
阿里云研究员、阿里云人工智能平台 PAI 技术负责人--林伟在GTC 2024 大会 China AI Day 线上中文演讲专场上介绍了TorchAcc,这是一个基于 PyTorch/XLA 的大模型分布式训练框架。
|
1月前
|
SQL 弹性计算 分布式计算
TiDB计算层详解:分布式计算框架与查询优化机制
【2月更文挑战第26天】本文将深入剖析TiDB的计算层,详细解析其分布式计算框架和查询优化机制。通过了解计算层的核心组件和工作原理,我们可以更好地理解TiDB如何高效处理SQL查询和计算任务。本文将从计算层的架构、任务分发、查询优化等方面展开介绍,帮助读者全面掌握TiDB计算层的关键技术和优势。
|
2月前
|
消息中间件 Kafka Apache
Apache Flink 是一个开源的分布式流处理框架
Apache Flink 是一个开源的分布式流处理框架
483 5
|
29天前
|
消息中间件 算法 Java
【亿级数据专题】「分布式服务框架」 盘点本年度我们探索服务的保障容量的三大关键方案实现
【亿级数据专题】「分布式服务框架」 盘点本年度我们探索服务的保障容量的三大关键方案实现
187 0
|
2月前
|
监控 负载均衡 Dubbo
Dubbo 框架揭秘:分布式架构的精髓与魔法【一】
Dubbo 框架揭秘:分布式架构的精髓与魔法【一】
162 0
|
1月前
|
运维 监控 Java
推荐一款好用的Java分布式任务调度框架!
推荐一款好用的Java分布式任务调度框架!
168 0
|
3月前
|
存储 安全 JavaScript
【分布式技术专题】「授权认证体系」深度解析OAuth2.0协议的原理和流程框架实现指南(授权流程和模式)
在传统的客户端-服务器身份验证模式中,客户端请求服务器上访问受限的资源(受保护的资源)时,需要使用资源所有者的凭据在服务器上进行身份验证。资源所有者为了给第三方应用提供受限资源的访问权限,需要与第三方共享它的凭据。这就导致一些问题和局限:
373 2
【分布式技术专题】「授权认证体系」深度解析OAuth2.0协议的原理和流程框架实现指南(授权流程和模式)
|
3天前
|
Dubbo Java 应用服务中间件
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
|
5月前
|
SQL NoSQL 关系型数据库
分布式系列教程(21) -分布式事务解决方案(框架篇)
分布式系列教程(21) -分布式事务解决方案(框架篇)
71 0

热门文章

最新文章