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

相关推荐
我叫珂蛋儿吖23 分钟前
[redis进阶六]详解redis作为缓存&&分布式锁
运维·c语言·数据库·c++·redis·分布式·缓存
撸猫7911 小时前
HttpSession 的运行原理
前端·后端·cookie·httpsession
嘵奇2 小时前
Spring Boot中HTTP连接池的配置与优化实践
spring boot·后端·http
椰椰椰耶2 小时前
【RabbitMQ】工作队列和发布/订阅模式的具体实现
分布式·rabbitmq·ruby
子燕若水2 小时前
Flask 调试的时候进入main函数两次
后端·python·flask
程序员爱钓鱼2 小时前
跳转语句:break、continue、goto -《Go语言实战指南》
开发语言·后端·golang·go1.19
猪猪果泡酒3 小时前
Spark,RDD中的行动算子
大数据·分布式·spark
Persistence___3 小时前
SpringBoot中的拦截器
java·spring boot·后端
2401_871290583 小时前
Spark处理过程-转换算子
大数据·分布式·spark
Betty_蹄蹄boo3 小时前
运行Spark程序-在Spark-shell——RDD
大数据·分布式·spark