当前位置: 首页 > backend >正文

Spring Boot 整合 Lock4j + Redisson 实现分布式锁实战

本文基于 Spring Boot 2.7.x + MyBatis Plus 3.5.9,演示如何通过 Lock4j 与 Redisson 实现高可靠的分布式锁方案,解决高并发场景下的资源竞争问题。


一、依赖配置关键点

1.1 Maven 依赖(pom.xml)

			 <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.41.0</version><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></exclusion><exclusion><groupId>org.redisson</groupId><!-- 使用 redisson-spring-data-27 替代,解决 Tuple NoClassDefFoundError 报错 --><artifactId>redisson-spring-data-34</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-data-27</artifactId><version>3.41.0</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>lock4j-redisson-spring-boot-starter</artifactId><version>2.2.7</version><exclusions><exclusion><artifactId>redisson-spring-boot-starter</artifactId><groupId>org.redisson</groupId></exclusion></exclusions></dependency>

1.2 依赖关系说明

依赖作用版本控制策略
lock4j-redisson-*Lock4j 分布式锁核心实现继承自项目 BOM 统一管理
redisson-spring-boot-starterRedisson 客户端 Starter显式指定版本保证兼容性
redisson-spring-data-27Spring Data 2.7 适配模块与 Spring Boot 2.7.x 版本严格对应

二、为什么需要显式排除依赖?

2.1 解决版本冲突问题

  • Lock4j 默认依赖的 Redisson 版本可能较低,通过 <exclusions> 排除后使用项目统一管理的 Redisson 3.41.0
  • Spring Data 版本适配:Spring Boot 2.7.x 对应 Spring Data 2.7,需使用 redisson-spring-data-27 模块

2.2 避免不必要依赖

  • 排除 spring-boot-starter-actuator:若项目未使用监控端点,减少无用依赖
  • 排除 redisson-spring-data-34:防止与 Spring Data 2.7 产生兼容性问题

三、配置验证(application.yml)

spring:# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优redis:host: 127.0.0.1 # 地址port: 6379 # 端口database: 0 # 数据库索引password: 123456 # 密码,建议生产环境开启
# Lock4j 配置项
lock4j:acquire-timeout: 3000 # 获取锁等待超时时间,默认为 3000 毫秒expire: 30000 # # 默认锁过期时间(毫秒),默认为 30 毫秒store-type: redis # 使用 Redis 实现

四、锁失败策略配置(核心防御机制)

4.1 DefaultLockFailureStrategy 源码解析

/*** 自定义获取锁失败策略,抛出 {@link ServiceException} 异常*/
@Slf4j
public class DefaultLockFailureStrategy implements LockFailureStrategy {@Overridepublic void onLockFailure(String key, Method method, Object[] arguments) {log.debug("[onLockFailure][线程:{} 获取锁失败,key:{} 获取失败:{} ]", Thread.currentThread().getName(), key, arguments);throw new ServiceException(GlobalErrorCodeConstants.LOCKED);}
}

关键设计点:

  • 日志分级:使用 debug 级别避免生产环境日志膨胀
  • 异常标准化:通过 GlobalErrorCodeConstants.LOCKED 统一返回 “请求过于频繁” 提示
  • 上下文保留:记录线程、锁Key、方法参数等关键信息便于问题排查

五、自动装配机制(集成关键)

5.1 DyhLock4jConfiguration 配置类

@AutoConfiguration(before = LockAutoConfiguration.class)
@ConditionalOnClass(name = "com.baomidou.lock.annotation.Lock4j")
public class DyhLock4jConfiguration {@Beanpublic DefaultLockFailureStrategy lockFailureStrategy() {return new DefaultLockFailureStrategy();}}

注解解析:

注解作用
@AutoConfigurationSpring Boot 3.0+ 新特性,替代传统 @Configuration 更精准控制加载顺序
before = LockAutoConfiguration.class确保在 Lock4j 默认配置前加载,避免 Bean 冲突
@ConditionalOnClass存在 Lock4j 注解时才生效,实现条件化装配

5.2 配置类加载流程说明

流程分解

1. Spring Boot 启动│└─▶ 扫描所有 AutoConfiguration 类│├─▶ 检测是否存在 Lock4j 注解(@ConditionalOnClass)│    ││    ├─ 存在 → 加载 DyhLock4jConfiguration│    │       ││    │       └─▶ 注册 DefaultLockFailureStrategy Bean│    │              ││    │              └─▶ 初始化 Lock4j 组件│    ││    └─ 不存在 → 跳过分布式锁配置│└─▶ 继续其他自动配置

关键节点说明

步骤说明对应代码片段
条件检测@ConditionalOnClass 注解检查 classpath 是否存在 com.baomidou.lock.annotation.Lock4j 类@ConditionalOnClass(name = “com.baomidou.lock.annotation.Lock4j”)
配置顺序控制@AutoConfiguration(before = LockAutoConfiguration.class) 确保自定义配置在 Lock4j 默认配置前加载@AutoConfiguration(before = LockAutoConfiguration.class)
Bean 注册通过 @Bean 注解将失败策略注入 Spring 容器@Bean public DefaultLockFailureStrategy lockFailureStrategy()

六、实战开发示例

@Service
@RequiredArgsConstructor
public class OrderService {private final OrderMapper orderMapper;// 分布式锁注解@Lock4j(name = "order_create_#{#orderDTO.userId}", // 动态锁名(SpEL)expire = 10000,      // 锁自动释放时间(毫秒)acquireTimeout = 2000 // 获取锁等待时间)@Transactionalpublic void createOrder(OrderDTO orderDTO) {// 1. 幂等校验Order existOrder = orderMapper.selectByUserId(orderDTO.getUserId());if (existOrder != null) {throw new ServiceException("订单已存在");}// 2. 业务操作(如扣减库存)reduceStock(orderDTO.getProductId());// 3. 创建订单Order order = new Order().setUserId(orderDTO.getUserId());orderMapper.insert(order);}
}
http://www.xdnf.cn/news/1808.html

相关文章:

  • YOLOv11架构革新——基于RFEM模块的小目标感受野增强与特征优化
  • 如何管理“完美主义”导致的进度拖延
  • 高德地图API + three.js + Vue3基础使用与使用 + 标记不显示避坑
  • IMX6ULL 最新方案移植教程中间间系列5——向开发板迁移SSH和FTP
  • LeetCode hot 100—最长有效括号
  • 【FAQ】安装Agent的主机,为何不能更改显示分辨率
  • CVE-2025-32102 | Ubuntu 下复现 CrushFTP telnetSocket接口SSRF
  • dataType 和 content-type 参数的作用
  • 补4月22日23日
  • Sentieon软件发布V202503版本
  • 首版次软件产品有哪些阶段?专业软件测试服务公司分享
  • 使用String path = FileUtilTest.class.getResource(“/1.txt“).getPath(); 报找不到路径
  • Spring Boot 中配置线程池时优化 `ThreadPoolTaskExecutor` 的配置总结
  • DDL小练习
  • Java小公司实习面经
  • python字符串(3):字符集/编码(查看修改字符集,乱码);码点和字符的转换(chr和ord),字符串的编码解码函数(encode,decode)
  • Dockerfile指令
  • JavaScript 实现继承及 Class 本质详解
  • 【Python Web开发】02-Socket网络编程02
  • Java 高频面试题解析
  • Langchain提取结构化数据
  • 第九节:性能优化高频题-首屏加载优化策略
  • JS Array 方法 | 区分 slice 和 splice
  • `rfind()` 从字符串的右侧开始查找指定子字符串首次出现的位置
  • SiamFC算法深度解析
  • 深入浅出:Pinctrl与GPIO子系统详解
  • SpringCloud微服务架构设计与实践 - 面试实战
  • C语言别踩白块附源码
  • Trae+DeepSeek学习Python开发MVC框架程序笔记(四):使用sqlite存储查询并验证用户名和密码
  • 现代化个人博客系统 ModStartBlog v10.3.0 博客批量操作,博客评论智能审核,安全升级