Redisson 实现分布式锁简单解析

news2025/4/21 14:46:19

目录

  • Redisson 实现分布式锁
    • 业务方法:
    • 加锁逻辑
      • LockUtil 工具类
        • 锁余额方法:
          • 工具类代码
          • 枚举代码
      • RedisUtil 工具类
        • tryLock 方法及重载【分布式锁具体实现】
        • Supplier 函数式接口调用分析

Redisson 实现分布式锁

业务方法:

如图,简单的执行一个增加余额的方法,为保证数据一致性,那么可以通过Redisson分布式锁来实现。
在这里插入图片描述

加锁逻辑

LockUtil 工具类

锁余额方法:

在这里插入图片描述

工具类代码
/**
 * @author lujinhong
 * @since  2025/3/25
 */
public class LockUtil {

    /**
     * 锁商家余额
     *
     * @param business 商家id
     * @param supplier 函数式接口;代表一个无参但有返回值的函数,就是代表加锁后要执行的业务逻辑
     * @param lockFail 加锁失败后执行的自定义业务逻辑,这里就是一个简单的抛异常
     */
    public static <T> T businessBalance(Integer business, Supplier<T> supplier, InvokeInter lockFail) {
        return tryLock(RedisKey.LOCK_BUSINESS_BALANCE.getKey(business), supplier, lockFail);
    }
}
枚举代码
/**
 * @author lujinhong
 * @since  2025/3/25
 */
@Getter
@AllArgsConstructor
public enum RedisKey {

    // 商家余额
    LOCK_BUSINESS_BALANCE("lock_business_balance_");

    private final String key;

    public String getKey(Number number) {
        return key + number;
    }
}

RedisUtil 工具类

tryLock 方法及重载【分布式锁具体实现】

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


/**
 * @author lujinhong
 * @since  2025/3/25
 */
@Slf4j
@Component
public class RedisUtil {

    public static RedisUtil _this;

    @Resource
    private RedissonClient redissonClient;

    @PostConstruct
    public void init() {
        _this = this;
    }

    /**
     * 设置分布式锁
     *
     * @param key      就是上面用商家id生成的一个key
     * @param supplier 函数式接口,加锁后要执行的业务逻辑
     * @param lockFail 加锁失败后执行的业务逻辑:这里是抛异常
     */
    public static <T> T tryLock(String key, Supplier<T> supplier, InvokeInter lockFail) {
        return tryLock(key, supplier, lockFail, 10, TimeUnit.SECONDS);
    }



    /**
     * 设置分布式锁--具体实现
     * <p>
     * 注意事项1:.getLock(key):用商家Id作为key生成一个rLock对象,底层代码是通过new来创建实例的,也就是说不同线程操作同一个商家获取到的是不同的RLock实例,
     * -----------重点来了:虽然 RLock 实例在 Java 层是不同的,但是它们 指向同一个 Redis 锁,这个锁的标识是由 key(比如 LOCK_BUSINESS_BALANCE:1001)决定的。
     * --------------------所以才需要在加锁之前,判断当前这个锁实例是否被其他线程占用了等判断--> if (lock.isLocked() && !lock.isHeldByCurrentThread())
     * <p>
     * 锁实例:RLock 是一个 Java 对象,代表分布式锁,它操作 Redis 中的实际锁资源。
     * 锁资源:是 Redis 中的一个 key,用于标识是否已被某个线程持有,实际上是分布式锁的底层实现。
     * <p>
     * 获取锁,其实就是当前线程获得了对某个共享资源的独占访问权限
     * <p>
     * lock.isHeldByCurrentThread() 的底层实现依赖于 Redis 中 锁的 value 存储了持有锁的线程的 ID。该方法通过查询 Redis 锁的 value,并与当前线程的 ID 比较,来判断当前线程是否持有该锁
     *
     * @param key      用来生成 RLock 锁实例的key
     * @param supplier 函数式接口,在加锁成功后执行的业务逻辑
     * @param lockFail 加锁失败后执行的业务逻辑
     * @param amount   当前线程在获取锁时最多等待的时间【注意是获取锁的时间,不是获取到该锁后锁的存活时间】,就是给你多少时间去获取锁
     * @param unit     时间单位
     */
    public static <T> T tryLock(String key, Supplier<T> supplier, InvokeInter lockFail, long amount, TimeUnit unit) {

        // 创建一个 redisson 分布式锁的锁实例:
        // 这个实例并不是直接获取Redis里的锁,而是一个Java对象,它是 Redisson 对 Redis 分布式锁的封装,用于后续操作:
        // 如 加锁tryLock()、释放锁unlock()、查询锁状态 isLocked()
        RLock lock = _this.redissonClient.getLock(key);

        try {
            // lock.isLocked():判断的是 Redis 中该 key(锁资源)是否已经被其他线程或进程获取。
            // !lock.isHeldByCurrentThread():判断当前线程是否持有该锁,就是通过 Redis 中的 key 来检查是否是当前线程获得了该锁
            if (lock.isLocked() && !lock.isHeldByCurrentThread()) {
                if (lockFail == null) {
                    // 直接抛异常
                    throw BizException.newInstance(ErrorCode.BUSY);
                }
                // 如果有自定义的加锁失败逻辑,则执行
                lockFail.invoke();
            }
            // 真正的加锁:在指定时间(amount)内获取锁,获取不到则返回false;
            // 问题:lock.tryLock获取到锁之后,redis内部是做了什么操作:其实就是操作了一句 setNx 命令而已。
            else if (lock.tryLock(amount, unit)) {
                try {
                    // 执行具体的业务逻辑
                    return supplier.get();
                } finally {
                    // 释放锁
                    lock.unlock();
                }
            } else {
                // 上面没获取到锁,则报错
                if (lockFail == null) {
                    // 默认就抛这个异常
                    throw BizException.newInstance(ErrorCode.BUSY);
                }
                // 如果有自定义的异常处理,则执行
                lockFail.invoke();
            }
            return null;
        } catch (InterruptedException e) {
            throw BizException.newInstance(ErrorCode.BUSY);
        }
    }

}

Supplier 函数式接口调用分析

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2322207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

信源的分类及数学模型

信源的分类及数学模型 按照信源发出的时间和消息分布分为离散信源和连续信源 按照信源发出符号之间的关系分为无记忆信源和有记忆信源 单符号离散信源&#xff08;一维离散信源&#xff09; 信源输出的消息数有限或可数&#xff0c;且每次只输出符号集的一个消息 样本空间&…

LVS NAT模式实现三台RS的轮询访问

节点规划: 配置RS&#xff1a; RS1-RS3的网关配置均为 192.168.163.8 配置RS1&#xff1a; [rootlocalhost ~]# hostnamectl hostname rs1 [rootlocalhost ~]# nmcli c modify ens160 ipv4.method manual ipv4.addresses 192.168.163.7/24 ipv4.gateway 192.168.163.8 conne…

LSM-Tree(Log-Structured Merge-Tree)详解

1. 什么是 LSM-Tree? LSM-Tree(Log-Structured Merge-Tree)是一种 针对写优化的存储结构,广泛用于 NoSQL 数据库(如 LevelDB、RocksDB、HBase、Cassandra)等系统。 它的核心思想是: 写入时只追加写(Append-Only),将数据先写入内存缓冲区(MemTable)。内存数据满后…

uni-app jyf-parser将字符串转化为html 和 rich-text

uni-app jyf-parser将字符串转化为html-CSDN博客 方法二&#xff1a; rich-text | uni-app

Docker+Ollama+Xinference+RAGFlow+Dify部署及踩坑问题

目录 一、Xinference部署 &#xff08;一&#xff09;简介 &#xff08;二&#xff09;部署 &#xff08;三&#xff09;参数 &#xff08;四&#xff09;错误问题 &#xff08;五&#xff09;Xinference配置Text-embedding模型 &#xff08;六&#xff09;Xinference配…

【机器学习】什么是线性回归?

什么是线性回归&#xff1f; 线性回归是一种 监督学习算法&#xff0c;它通过拟合一个直线&#xff08;或平面&#xff0c;高维空间下是超平面&#xff09;来建立 输入特征 和 输出目标 之间的关系。简单来说&#xff0c;线性回归就是找出一个数学方程&#xff08;通常是线性方…

零、ubuntu20.04 安装 anaconda

1.anaconda下载 地址&#xff1a;Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 选择&#xff1a;Anaconda3-2023.07-2-Linux-x86_64.sh 2.anaconda安装 选择下载目录&#xff0c;选在在终端中打开&#xff0c;然后在终端输入安装命…

Web纯前端实现在线打开编辑保存PPT幻灯片

很多项目中有时会需要在线打开PPT并编辑保存到服务器。猿大师办公助手可以完美调用本地office在线打开ppt文件&#xff0c;跟本地打开效果一样。还可以在线打开word、excel、pdf等文件&#xff0c;支持本机OFFICE完整嵌入模式&#xff0c;本机OFFICE所有功能基本都可以在网页上…

LeetCode热题100精讲——Top3:最长连续序列【哈希】

你好&#xff0c;我是安然无虞。 文章目录 题目背景最长连续序列C解法Python解法 题目背景 如果大家对于 哈希 类型的概念并不熟悉, 可以先看我之前为此专门写的算法详解: 蓝桥杯算法竞赛系列第九章巧解哈希题&#xff0c;用这3种数据类型足矣 最长连续序列 题目链接&#x…

2025年渗透测试面试题总结-某 长亭(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 长亭 一、Spring SpEL表达式注入漏洞 1. 技术原理 2. 利用条件 3. 攻击方法 4. 防御策略 二、Jav…

Ubuntu部署Dufs文件服务器

安装dufs 安装cargo apt install cargo升级rust工具链 apt install rustup rustup update stable查看rust版本&#xff0c;需要>1.81 rustc --version安装dufs cargo install dufs将dufs加入环境变量 sudo vim ~/.bashrc export PATH"$HOME/.cargo/bin:$PATH" sou…

前端模拟 websocket 请求小工具

背景&#xff1a; 后端写好websocket 接口后&#xff0c;用postman的某些版本无法直接模拟websocket请求&#xff0c;所以想着自制一个小工具。 使用方法&#xff1a; 直接复制以下代码到文本文件中&#xff0c;修改服务端端地址&#xff0c;保存为 .html的后缀名&#xff0c;…

【极速版 -- 大模型入门到进阶】快速了解大型语言模型

文章目录 &#x1f30a; 大模型作为一种生成式人工智慧&#xff0c;厉害在哪儿&#xff1f;-> 通用能力&#x1f30a; LLM 如何生成输出&#xff1a;简而言之就是文字接龙&#x1f30a; GPT 之前 ...&#xff1a;模型规模和数据规模概览&#x1f30a; ChatGPT 有三个训练阶段…

精选10个好用的WordPress免费主题

10个好用的WordPress免费主题 1. Astra Astra 是全球最受欢迎的 WordPress 主题。它功能丰富&#xff0c;易于使用&#xff0c;SEO友好&#xff0c;是第一个安装量突破100万的非默认主题&#xff0c;并获得了5000多个五星好评。 它完美集成了Elementor、Beaver&#xff0c;古…

算法日常刷题笔记(6)

重整旗鼓 第六篇笔记 第一天 使字符串平衡的最小交换次数 给你一个字符串 s &#xff0c;下标从 0 开始 &#xff0c;且长度为偶数 n 。字符串 恰好 由 n / 2 个开括号 [ 和 n / 2 个闭括号 ] 组成。 只有能满足下述所有条件的字符串才能称为 平衡字符串 &#xff1a; 字符串…

【Unity3D脚本与系统设计6】鼠标触摸超时待机实现

实现步骤 在Unity中实现一个功能&#xff0c;当鼠标或触摸超过一定时间没有操作时&#xff0c;自动返回待机界面。 检测输入 首先&#xff0c;我需要检测用户的输入&#xff0c;无论是鼠标还是触摸。Unity的Input系统可以检测到鼠标和触摸事件&#xff0c;比如Input.GetAxis…

C++学习之路:从头搞懂配置VScode开发环境的逻辑与步骤

目录 编辑器与IDE基于vscode的C开发环境配置1. 下载vscode、浅尝编译。番外篇 2. 安装插件&#xff0c;赋能编程。3. 各种json文件的作用。c_cpp_properties.jsontask.jsonlaunch.json 总结&&彩蛋 编辑器与IDE 上一篇博客已经介绍过了C程序的一个编译流程&#xff0c;从…

Web3与网络安全:如何确保去中心化应用的安全性

Web3与网络安全&#xff1a;如何确保去中心化应用的安全性 随着区块链技术的蓬勃发展&#xff0c;Web3的概念逐渐成为互联网发展的新趋势。Web3强调去中心化、用户主权和数据隐私&#xff0c;它的核心是构建一个更加开放、透明和安全的网络环境。然而&#xff0c;随着去中心化…

插值法笔记 ——武汉理工统计 周

第二章 插值法 插值法定义 插值函数定义 设函数 y f ( x ) y f(x) yf(x) 在区间 [a,b] 上有定义&#xff0c;且满足节点排列&#xff1a; a ≤ x 0 < x 1 < ⋯ < x n ≤ b a \leq x_0 < x_1 < \cdots < x_n \leq b a≤x0​<x1​<⋯<xn​≤b …

23种设计模式-命令(Command)设计模式

命令设计模式 &#x1f6a9;什么是命令设计模式&#xff1f;&#x1f6a9;命令设计模式的特点&#x1f6a9;命令设计模式的结构&#x1f6a9;命令设计模式的优缺点&#x1f6a9;命令设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是命令设计模式…