当前位置: 首页 > article >正文

Spring Boot + Redisson 封装分布式锁

目标:一行代码调用,简单粗暴。
基操:自动加锁,自动解锁,自动处理异常,自动处理锁超时等。

安装

redis + redisson

        <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 工具类

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>

配置

spring:
  data:
    redis:
      host: xxx
      port: 6379
      password: xxx
      database: x

配置类

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 {
}

工具类

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;
    }

}

测试

    @GetMapping("/lock/{key}")
    public String lock(@PathVariable String key) {
        return RedissonUtil.lock(key, () -> {

            ThreadUtil.sleep(30 * 1000);

            return "出参";
        });
    }
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


http://www.kler.cn/a/459954.html

相关文章:

  • 第J4周:ResNet与DenseNet结合探索
  • 让私域用户付费的三个关键要素
  • 【PS不常见教程】实操篇之通道抠图-抠黑色背景的图片
  • 苍穹外卖 项目记录 day01
  • Linux系统在任意目录运行py脚本
  • 数据库进阶教程之DDL语句(万字详解)
  • NLP 中文拼写检测纠正论文 C-LLM Learn to CSC Errors Character by Character
  • vue3中使用el-tag结合element-plus使用方法
  • RuntimeError: CUDA error: initialization
  • sqlserver镜像设置
  • 基于 Python Django 的二手电子设备交易平台(附源码,文档)
  • C#学习1:C#初接触,一些基础内容备忘和相关报错说明
  • libmodbus源码中重要的两个结构体讲解
  • IndexOf Apache Web For Liunx索引服务器部署及应用
  • docker使用国内镜像
  • 批次特征组杂记
  • Unity 开发中可能用到的类型
  • 聊一聊GPT基本原理
  • word怎么添加链接,点击直接到参考文献
  • ID卡网络读卡器C#小程序开发
  • 视觉语言模型易受攻击?西安交大等提出基于扩散模型的对抗样本生成新方法
  • Kali Linux 文件系统详解
  • Python跨年烟花
  • 机器学习之数据分析及特征工程详细分析过程
  • Object.defineProperty() 完整指南
  • nginx平滑升级|nginx升级|解决漏洞CVE-2024-7347