• lock4j--分布式锁中间件--​自定义获取锁失败的逻辑


    原文网址:lock4j--分布式锁中间件--​自定义获取锁失败的逻辑_IT利刃出鞘的博客-CSDN博客

    简介

    说明

            本文介绍lock4j如何自定义获取锁失败的逻辑。

    概述

            在注解模式下,对某个方法加锁,如果方法已上锁,默认抛出异常。默认的锁获取失败策略为 com.baomidou.lock.DefaultLockFailureStrategy 。

            可以自定义处理方法,比如:如果方法上锁,其他线程执行时放弃执行,而不是抛异常。

    相关网址

    gitee:https://gitee.com/baomidou/lock4j

    自定义获取锁失败逻辑:gitee官方测试用例

    注意

    本处使用lock4j过程中遇到了问题,不推荐使用lock4j,推荐直接使用redisson的分布式锁。

    遇到的问题:

    1. 获取锁超时时并没有抛异常,而是一直等待获取到锁。(无论是默认策略还是自定义策略都是如此)。

    方法概述

    自定义实现类,实现LockFailureStrategy接口。

    1. import com.baomidou.lock.LockFailureStrategy;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.stereotype.Component;
    4. import java.lang.reflect.Method;
    5. /**
    6. * 自定义获取锁异常处理
    7. */
    8. @Slf4j
    9. @Component
    10. public class CustomLockFailureStrategy implements LockFailureStrategy {
    11. @Override
    12. public void onLockFailure(String key, Method method, Object[] arguments) {
    13. log.error("获取锁失败了,key={},method={},arguments={}", key, method, arguments);
    14. // 此处可以抛出指定异常,配合全局异常拦截包装统一格式返回给调用端
    15. throw new BusinessException("请求太快啦~");
    16. }
    17. }

     默认的策略:DefaultLockFailureStrategy

    1. package com.baomidou.lock;
    2. import com.baomidou.lock.exception.LockFailureException;
    3. import lombok.extern.slf4j.Slf4j;
    4. import java.lang.reflect.Method;
    5. /**
    6. * @author zengzhihong
    7. */
    8. @Slf4j
    9. public class DefaultLockFailureStrategy implements LockFailureStrategy {
    10. protected static String DEFAULT_MESSAGE = "request failed,please retry it.";
    11. @Override
    12. public void onLockFailure(String key, Method method, Object[] arguments) {
    13. throw new LockFailureException(DEFAULT_MESSAGE);
    14. }
    15. }

    公共代码

    配置

    1. spring:
    2. redis:
    3. host: 192.168.5.193
    4. port: 6379
    5. password: 222333
    6. #lock4j:
    7. # acquire-timeout: 3000 #默认值3s,可不设置。排队时长,超过就退出排队,抛出获取锁超时异常。
    8. # expire: 30000 #默认值30s,可不设置
    9. # primary-executor: com.baomidou.lock.executor.RedissonLockExecutor #默认redisson > redisTemplate > zookeeper,可不设置
    10. # lock-key-prefix: lock4j #锁key前缀, 默认值lock4j,可不设置

    依赖

    1. <!-- https://mvnrepository.com/artifact/com.baomidou/lock4j-redisson-spring-boot-starter -->
    2. <dependency>
    3. <groupId>com.baomidou</groupId>
    4. <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
    5. <version>2.2.2</version>
    6. </dependency>

    整个pom.xml

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0</modelVersion>
    5. <parent>
    6. <groupId>org.springframework.boot</groupId>
    7. <artifactId>spring-boot-starter-parent</artifactId>
    8. <version>2.4.13</version>
    9. <relativePath/> <!-- lookup parent from repository -->
    10. </parent>
    11. <groupId>com.knife.demo</groupId>
    12. <artifactId>demo_lock4j_SpringBoot</artifactId>
    13. <version>0.0.1-SNAPSHOT</version>
    14. <name>demo_lock4j_SpringBoot</name>
    15. <description>demo_lock4j_SpringBoot</description>
    16. <properties>
    17. <java.version>1.8</java.version>
    18. </properties>
    19. <dependencies>
    20. <dependency>
    21. <groupId>org.springframework.boot</groupId>
    22. <artifactId>spring-boot-starter-web</artifactId>
    23. </dependency>
    24. <!-- https://mvnrepository.com/artifact/com.baomidou/lock4j-redisson-spring-boot-starter -->
    25. <dependency>
    26. <groupId>com.baomidou</groupId>
    27. <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
    28. <version>2.2.2</version>
    29. </dependency>
    30. <dependency>
    31. <groupId>org.projectlombok</groupId>
    32. <artifactId>lombok</artifactId>
    33. <optional>true</optional>
    34. </dependency>
    35. <dependency>
    36. <groupId>com.github.xiaoymin</groupId>
    37. <artifactId>knife4j-spring-boot-starter</artifactId>
    38. <version>3.0.3</version>
    39. </dependency>
    40. </dependencies>
    41. <build>
    42. <plugins>
    43. <plugin>
    44. <groupId>org.springframework.boot</groupId>
    45. <artifactId>spring-boot-maven-plugin</artifactId>
    46. <configuration>
    47. <excludes>
    48. <exclude>
    49. <groupId>org.projectlombok</groupId>
    50. <artifactId>lombok</artifactId>
    51. </exclude>
    52. </excludes>
    53. </configuration>
    54. </plugin>
    55. </plugins>
    56. </build>
    57. </project>

    代码

    Controller

    1. package com.knife.demo.controller;
    2. import com.baomidou.lock.annotation.Lock4j;
    3. import com.knife.demo.entity.User;
    4. import io.swagger.annotations.Api;
    5. import lombok.extern.slf4j.Slf4j;
    6. import org.springframework.web.bind.annotation.GetMapping;
    7. import org.springframework.web.bind.annotation.RequestMapping;
    8. import org.springframework.web.bind.annotation.RestController;
    9. import java.util.ArrayList;
    10. import java.util.List;
    11. @Api(tags = "用户")
    12. @Slf4j
    13. @RestController
    14. @RequestMapping("user")
    15. public class UserController {
    16. @GetMapping("listAll")
    17. @Lock4j
    18. public List<User> listAllUser() {
    19. try {
    20. log.info("获取到锁,开始睡眠");
    21. Thread.sleep(15000);
    22. } catch (InterruptedException e) {
    23. throw new RuntimeException(e);
    24. }
    25. return new ArrayList<>();
    26. }
    27. @GetMapping("find")
    28. @Lock4j(keys = {"#user.id", "#user.name"}, expire = 60000, acquireTimeout = 1000)
    29. public List<User> find(User user) {
    30. return new ArrayList<>();
    31. }
    32. }

    Entity

    1. package com.knife.demo.entity;
    2. import lombok.Data;
    3. @Data
    4. public class User {
    5. private Long id;
    6. private String name;
    7. }

    实例1:默认的获取锁失败策略

    短时间内访问两次这个接口:http://localhost:8080/user/listAll

    可以看到:获取锁超时时并没有抛异常,而是一直等待获取到锁。

    后端结果

    实例2:自定义锁获取失败策略

    自定义策略

    1. package com.knife.demo.config;
    2. import com.baomidou.lock.LockFailureStrategy;
    3. import lombok.extern.slf4j.Slf4j;
    4. import org.springframework.stereotype.Component;
    5. import java.lang.reflect.Method;
    6. @Slf4j
    7. @Component
    8. public class CustomLockFailureStrategy implements LockFailureStrategy {
    9. @Override
    10. public void onLockFailure(String key, Method method, Object[] arguments) {
    11. log.error("获取锁失败了。key={},method={},arguments={}", key, method, arguments);
    12. // 此处可以抛出指定异常,配合全局异常拦截包装统一格式返回给调用端
    13. throw new RuntimeException("请求太快啦~");
    14. }
    15. }

    短时间内访问两次这个接口:http://localhost:8080/user/listAll

    结果:获取锁超时时并没有抛异常,而是一直等待获取到锁。

    后端结果:

     

  • 相关阅读:
    简单了解CyclicBarrier
    人先自辱,而后人辱之
    【.NET CORE】yisha框架校验输入内容
    C++ 使用c++类模板实现动态数组-可实现自定义数据类型存储
    借用binlog2sql工具轻松解析MySQL的binlog文件,再现Oracle的闪回功能
    Android 内存泄漏分析思路和案例剖析
    Linux常用命令
    面试题 02.07. 链表相交-双指针法
    MYSQL锁
    Jenkins系列-安装maven
  • 原文地址:https://blog.csdn.net/feiying0canglang/article/details/125321139