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

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


一、依赖配置关键点

1.1 Maven 依赖(pom.xml)

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-starter Redisson 客户端 Starter 显式指定版本保证兼容性
redisson-spring-data-27 Spring 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)

yaml 复制代码
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 源码解析

java 复制代码
/**
 * 自定义获取锁失败策略,抛出 {@link ServiceException} 异常
 */
@Slf4j
public class DefaultLockFailureStrategy implements LockFailureStrategy {

    @Override
    public 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 配置类

java 复制代码
@AutoConfiguration(before = LockAutoConfiguration.class)
@ConditionalOnClass(name = "com.baomidou.lock.annotation.Lock4j")
public class DyhLock4jConfiguration {

    @Bean
    public DefaultLockFailureStrategy lockFailureStrategy() {
        return new DefaultLockFailureStrategy();
    }

}

注解解析:

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

5.2 配置类加载流程说明

流程分解

text 复制代码
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()

六、实战开发示例

java 复制代码
@Service
@RequiredArgsConstructor
public class OrderService {
    private final OrderMapper orderMapper;

    // 分布式锁注解
    @Lock4j(
            name = "order_create_#{#orderDTO.userId}", // 动态锁名(SpEL)
            expire = 10000,      // 锁自动释放时间(毫秒)
            acquireTimeout = 2000 // 获取锁等待时间
    )
    @Transactional
    public 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);
    }
}
相关推荐
jack_xu1 小时前
高频面试题:如何保证数据库和es数据一致性
后端·mysql·elasticsearch
pwzs1 小时前
Java 中 String 转 Integer 的方法与底层原理详解
java·后端·基础
Asthenia04121 小时前
InnoDB文件存储结构与Socket技术(从Linux的FD到Java的API)
后端
普if加的帕1 小时前
java Springboot使用扣子Coze实现实时音频对话智能客服
java·开发语言·人工智能·spring boot·实时音视频·智能客服
Asthenia04121 小时前
RocketMQ 消息不丢失与持久化机制详解-生产者与Broker之间的详解
后端
Asthenia04122 小时前
Select、Poll、Epoll 详细分析与面试深度剖析/C代码详解
后端
烛阴2 小时前
Node.js中必备的中间件大全:提升性能、安全与开发效率的秘密武器
javascript·后端·express
南雨北斗2 小时前
WMware虚拟机下载方法(2025年4月)
后端