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

相关推荐
星栈5 分钟前
oh-my-pi工程级AI编码工使用体验
人工智能·后端·agent
立心者02 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端
AskHarries2 小时前
SEO 页面怎么生成
后端
爱吃牛肉的大老虎3 小时前
Rust对象之结构体,枚举,特性
开发语言·后端·rust
石榴3 小时前
NestJS 的请求到底经过了什么:装饰器、守卫、拦截器、管道与中间件如何配合
后端
Gopher_HBo3 小时前
moby-client客户端
后端
杨运交3 小时前
[055][调度模块]Spring动态任务调度框架的设计与实现
java·后端·spring
卷福同学5 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
Csvn6 小时前
📊 SQL 入门 Day 11:CASE 表达式:SQL 里的 if-else 魔法
后端·sql
QQ_21696290966 小时前
Spring Boot 养老院管理系统:从入住、护理到费用结算的全流程实现(源码可领)
java·spring boot·后端