Spring Boot + Redisson 封装分布式锁

目标:一行代码调用,简单粗暴。

基操:自动加锁,自动解锁,自动处理异常,自动处理锁超时等。

安装

redis + redisson

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.39.0</version>
        </dependency>

hutool 工具类

xml 复制代码
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>

配置

yml 复制代码
spring:
  data:
    redis:
      host: xxx
      port: 6379
      password: xxx
      database: x

配置类

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * 方便获取 Spring IOC 实例
 *
 * @author jason
 */
@Configuration
@Import(cn.hutool.extra.spring.SpringUtil.class)
public class BeanConf {
}

工具类

java 复制代码
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * Redisson 操作工具类
 *
 * @author jason
 */
@Slf4j
@Component
public class RedissonUtil {
    /**
     * 锁默认超时时间为(单位:秒)
     */
    private static final long LEASE_TIME = 10;

    @Autowired
    private RedissonClient redissonClient;

    public static RedissonUtil instance() {
        return SpringUtil.getBean(RedissonUtil.class);
    }

    /**
     * 获取可重入锁
     * <p>
     * 读写锁(RReadWriteLock)包括读锁和写锁两部分:
     * 读锁(Read Lock):允许多个读线程同时访问,但写线程会被阻塞。
     * 写锁(Write Lock):独占锁,保证同时只有一个写线程访问,同时也会阻塞其他读线程。
     */
    public static RLock getClint(String key) {
        return instance().redissonClient.getLock(key);
    }

    /**
     * 加锁
     */
    public static void lock(String key) {
        getClint(key).lock(LEASE_TIME, TimeUnit.SECONDS);
    }

    /**
     * 解锁
     */
    public static void unLock(String key) {
        if (getClint(key).isLocked()) {
            getClint(key).unlock();
        }
    }

    /**
     * 分布式锁,默认超时时间为 LEASE_TIME
     */
    public static <T> T lock(String lockKey, Supplier<T> supplier) {
        lockKey = "distributed:" + lockKey;

        log.info("加锁开始,线程:{}", ThreadUtil.currentThreadGroup().getName());
        RedissonUtil.lock(lockKey);
        log.info("加锁结束,线程:{}", ThreadUtil.currentThreadGroup().getName());
        try {
            log.info("执行代码块开始,线程:{}", ThreadUtil.currentThreadGroup().getName());
            T t = supplier.get();
            log.info("执行代码块结束,线程:{}", ThreadUtil.currentThreadGroup().getName());
            return t;
        } catch (Exception e) {
            log.error(StrUtil.format("执行异常,线程:{}", ThreadUtil.currentThreadGroup().getName()), e);
        } finally {
            RedissonUtil.unLock(lockKey);
            log.info("释放锁结束,线程:{}", ThreadUtil.currentThreadGroup().getName());
        }
        return null;
    }

}

测试

java 复制代码
    @GetMapping("/lock/{key}")
    public String lock(@PathVariable String key) {
        return RedissonUtil.lock(key, () -> {

            ThreadUtil.sleep(30 * 1000);

            return "出参";
        });
    }
cmd 复制代码
2024-12-26T11:07:41.307 xxx.util.RedissonUtil    : 加锁开始,线程:main
2024-12-26T11:07:41.315 xxx.util.RedissonUtil    : 加锁结束,线程:main
2024-12-26T11:07:41.315 xxx.util.RedissonUtil    : 执行代码块开始,线程:main
2024-12-26T11:08:11.323 xxx.util.RedissonUtil    : 执行代码块结束,线程:main
2024-12-26T11:08:11.338 xxx.util.RedissonUtil    : 释放锁结束,线程:main

源码

https://gitee.com/zhaomingjian/workspace_jason_demo/tree/master/spring-boot-seckill

相关推荐
高频因子挖掘机27 分钟前
QuantDash 明明安装成功,为什么 Python 还是无法 import?
后端·github·api
Java爱好狂.8 小时前
Java初学者如何一周速通SpringBoot!
java·spring boot·后端·spring·高并发·架构师·java面试
马良神笔10 小时前
2026 年Rag最近技术前沿总结
后端·python·django
程序猿DD10 小时前
同样10美元,OpenDesign和Command Code的DeepSeek V4.1 Flash额度到底有多少?
后端
高频因子挖掘机10 小时前
A股量化从日线升级到5分钟线:数据量增加后最先暴露哪些工程问题?
后端·github·api
高频因子挖掘机11 小时前
历史行情返回顺序变了,为什么按行号计算指标很危险?
后端·github·api
团子哒哒12 小时前
数组、切片和Map
后端
专注仿真12 小时前
ThinkPHP6 API接口开发实例:从零搭建RESTful风格接口
后端·php·restful
开心猴爷12 小时前
应对iOS审核4.3:可以使用 IpaGuard 来给属性名混淆的技术细节与平衡之道
后端·ios
1m5555555513 小时前
RAG 工程实战(五):正确知识已经进入 Prompt,为什么大模型还是会答错?
后端·面试