Spring Boot + Redisson 分布式锁示例案例

 更新时间:2025年12月10日 09:55:37   作者:沃心  
本文提供了一个完整的SpringBoot+Redisson分布式锁示例项目结构,包括Maven依赖、配置文件、Redisson配置类、业务服务层和控制器等,通过这个示例,可以实现分布式环境下的并发控制,感兴趣的朋友一起看看吧

下面为你提供一个完整的 Spring Boot + Redisson 分布式锁示例项目结构,包含:

  • Maven 依赖配置
  • Redisson 配置类(支持单机/集群)
  • 分布式锁工具封装
  • 控制器示例(模拟并发场景)
  • 测试方法建议

你可以直接复制到你的项目中使用。

📁 项目结构概览

src/
├── main/
│   ├── java/
│   │   └── com.example.redissonlock/
│   │       ├── RedissonLockApplication.java
│   │       ├── config/
│   │       │   └── RedissonConfig.java
│   │       ├── service/
│   │       │   ├── OrderService.java
│   │       │   └── impl/
│   │       │       └── OrderServiceImpl.java
│   │       └── controller/
│   │           └── OrderController.java
│   └── resources/
│       ├── application.yml
│       └── application-dev.yml (可选)
└── test/
    └── java/
        └── com.example.redissonlock/
            └── RedissonLockTest.java

1️⃣ Maven 依赖(pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version> <!-- 支持 JDK 17+ -->
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>redisson-lock-demo</artifactId>
    <version>1.0.0</version>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <!-- Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Redisson Starter (自动配置 RedissonClient) -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.25.2</version> <!-- 检查最新版:https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter -->
        </dependency>
        <!-- Lombok (可选,简化日志/Getter/Setter) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

注意redisson-spring-boot-starter 已包含 spring-boot-starter-data-redisredisson 核心包。

2️⃣ 配置文件(application.yml)

spring:
  application:
    name: redisson-lock-demo
  # Redis 连接配置(单机模式)
  redis:
    host: localhost
    port: 6379
    database: 0
    timeout: 2000ms
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
# Redisson 自定义配置(可选,如需调整看门狗等)
# 如果不配置,Redisson 会自动使用 spring.redis 下的连接信息

🔁 集群模式示例(替换 spring.redis):

spring:
  redis:
    cluster:
      nodes:
        - 192.168.1.10:7000
        - 192.168.1.10:7001
        - 192.168.1.10:7002
    password: your_password
    timeout: 2000ms

3️⃣ Redisson 配置类(可选,用于自定义)

⚠️ 如果只用单机 Redis,其实不需要写这个类redisson-spring-boot-starter 会自动创建 RedissonClient
但如果你需要自定义(如修改看门狗超时、启用 codec),可以添加:

// src/main/java/com/example/redissonlock/config/RedissonConfig.java
package com.example.redissonlock.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfig {
    @Value("${spring.redis.host}")
    private String redisHost;
    @Value("${spring.redis.port}")
    private int redisPort;
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://" + redisHost + ":" + redisPort)
              .setTimeout(3000)
              .setConnectionPoolSize(10);
        // 可选:调整看门狗超时(默认30秒)
        // config.setLockWatchdogTimeout(60000); // 60秒
        return Redisson.create(config);
    }
}

4️⃣ 业务服务层(带分布式锁)

// src/main/java/com/example/redissonlock/service/OrderService.java
package com.example.redissonlock.service;
public interface OrderService {
    void createOrder(String userId, String orderId);
}
// src/main/java/com/example/redissonlock/service/impl/OrderServiceImpl.java
package com.example.redissonlock.service.impl;
import com.example.redissonlock.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    private final RedissonClient redissonClient;
    public OrderServiceImpl(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }
    @Override
    public void createOrder(String userId, String orderId) {
        // 锁 key 建议包含业务唯一标识,避免全局锁
        String lockKey = "order:create:" + orderId;
        RLock lock = redissonClient.getLock(lockKey);
        try {
            // 尝试加锁:最多等待 3 秒,持有锁 30 秒(看门狗会自动续期)
            boolean isLocked = lock.tryLock(3, 30, TimeUnit.SECONDS);
            if (!isLocked) {
                log.warn("获取分布式锁失败,orderId={}", orderId);
                throw new RuntimeException("系统繁忙,请稍后再试");
            }
            log.info("线程 {} 获取锁成功,开始处理订单 {}", Thread.currentThread().getName(), orderId);
            // 模拟业务耗时(即使超过30秒也不会丢锁!)
            Thread.sleep(5000);
            // TODO: 真实业务逻辑(如扣库存、写DB)
            log.info("订单 {} 创建成功", orderId);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("订单处理被中断", e);
            throw new RuntimeException(e);
        } finally {
            // 安全释放锁(Redisson 会校验线程ID)
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("线程 {} 释放锁,orderId={}", Thread.currentThread().getName(), orderId);
            }
        }
    }
}

5️⃣ 控制器(用于测试)

// src/main/java/com/example/redissonlock/controller/OrderController.java
package com.example.redissonlock.controller;
import com.example.redissonlock.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;
    @GetMapping("/create-order")
    public String createOrder(@RequestParam String userId,
                              @RequestParam String orderId) {
        orderService.createOrder(userId, orderId);
        return "Order created: " + orderId;
    }
}

6️⃣ 启动类

// src/main/java/com/example/redissonlock/RedissonLockApplication.java
package com.example.redissonlock;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RedissonLockApplication {
    public static void main(String[] args) {
        SpringApplication.run(RedissonLockApplication.class, args);
    }
}

🧪 如何测试并发效果?

方法 1:使用 JMeter / Postman Runner

  • 发起多个并发请求到:
    GET http://localhost:8080/create-order?userId=U1&orderId=O1001
  • 观察日志:同一 orderId 的请求会串行执行

方法 2:单元测试(模拟多线程)

// src/test/java/com/example/redissonlock/RedissonLockTest.java
@Test
void testConcurrentOrderCreation() throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(5);
    CountDownLatch latch = new CountDownLatch(5);
    for (int i = 0; i < 5; i++) {
        executor.submit(() -> {
            try {
                orderService.createOrder("U1", "O1001"); // 相同 orderId
            } finally {
                latch.countDown();
            }
        });
    }
    latch.await(); // 等待所有线程完成
    executor.shutdown();
}

✅ 关键优势总结

特性说明
自动续期Watchdog 默认每 10s 续期一次,不怕业务超时
安全释放基于线程 ID 校验,不会误删其他线程的锁
可重入同一线程可多次加锁
无死锁风险即使应用 crash,锁也会在 watchdog 超时后释放
Spring Boot 集成简单starter 自动配置,开箱即用

📌 注意事项

  1. 锁 key 设计:务必带上业务唯一标识(如 order:{orderId}),避免锁粒度太大。
  2. 不要在锁内做远程调用:如 HTTP 请求、MQ 发送,可能因网络延迟导致锁持有时间过长。
  3. 监控锁状态:可通过 Redis CLI 查看:KEYS *order*TTL your_lock_key
  4. 生产环境 Redis 高可用:建议使用 Redis Cluster 或 Sentinel。

到此这篇关于完整的 Spring Boot + Redisson 分布式锁示例的文章就介绍到这了,更多相关Spring Boot Redisson 分布式锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot基于docx4j实现DOCX转PDF的具体方案

    SpringBoot基于docx4j实现DOCX转PDF的具体方案

    在日常项目开发中,我们经常遇到用户上传 Word( .docx)文件,希望后台自动生成 PDF,用于下载、归档或在线预览,本文将介绍一个完全开源、部署简单、纯 Java 的实现方案,感兴趣的小伙伴可以跟着小编一起来看看
    2025-11-11
  • java:程序包org.apache.ibatis.annotations不存在报错解决

    java:程序包org.apache.ibatis.annotations不存在报错解决

    这篇文章主要给大家介绍了关于java:程序包org.apache.ibatis.annotations不存在报错的解决方法,这个错误是我在直接导入springboot项目的时候报错的,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-04-04
  • mybatis的mapper对应的xml写法及配置详解

    mybatis的mapper对应的xml写法及配置详解

    这篇文章给大家介绍mybatis的mapper对应的xml写法及配置详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-05-05
  • Java集合Stack源码详解

    Java集合Stack源码详解

    java工具包中的Stack是继承于Vector(矢量队列)的,由于Vector是通过数组实现的,这就意味着,Stack也是通过数组实现的,而非链表。当然,我们也可以将LinkedList当作栈来使用!
    2018-05-05
  • java虚拟机中多线程总结

    java虚拟机中多线程总结

    在本篇内容中小编给大家分享的是关于java虚拟机中多线程的知识点总结内容,需要的朋友们参考学习下。
    2019-06-06
  • 深入解析面向对象编程在Java中的应用小结

    深入解析面向对象编程在Java中的应用小结

    本文详细介绍了面向对象编程的基本概念,包括类和对象、封装、继承和多态,通过具体的Java代码示例,展示了如何在Java中应用这些面向对象编程的核心思想,感兴趣的朋友跟随小编一起看看吧
    2025-01-01
  • SpringBoot实现简单的登录注册的项目实战

    SpringBoot实现简单的登录注册的项目实战

    本文主要介绍了SpringBoot实现简单的登录注册的项目实战,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 详解java中finalize的实现与相应的执行过程

    详解java中finalize的实现与相应的执行过程

    在常规的java书籍中,即会描述 object的finalize方法是用于一些特殊的对象在回收之前再做一些扫尾的工作,但是并没有说明此是如何实现的.本篇从java的角度(不涉及jvm以及c++),有需要的朋友们可以参考借鉴。
    2016-09-09
  • Java 程序初始化顺序

    Java 程序初始化顺序

    这篇文章主要介绍了Java 程序初始化顺序,在Java语言中,当实例化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有的类成员完成了初始化之后,才会调用对象所在类的构造函数创建对象,需要的朋友可以参考一下
    2022-01-01
  • Java实现一个简单的长轮询的示例代码

    Java实现一个简单的长轮询的示例代码

    长轮询是与服务器保持即时通信的最简单的方式,它不使用任何特定的协议,例如 WebSocket ,所以也不依赖于浏览器版本等外部条件的兼容性。本文将用Java实现一个简单的长轮询,需要的可以参考一下
    2022-08-08

最新评论