使用 lock4j-redis-template-spring-boot-starter 实现redis分布式锁

使用 lock4j-redis-template-spring-boot-starter 实现redis分布式锁

    • 1. 引入依赖
    • 2. 配置 Redis
    • 3. 使用分布式锁
    • 4. 自定义锁配置
    • 5. 处理锁获取失败的情况
    • 6. 高级用法
    • 7.样例

分布式锁是一种用于在分布式系统中实现并发控制的机制。在分布式系统中,由于多个节点同时访问共享资源,会出现脏读、写冲突等并发问题。分布式锁通过在共享资源的访问前获取锁,来限制只有一个节点可以访问共享资源,从而保证在同一时间只有一个节点可以执行共享资源的操作,避免并发问题的发生。

分布式锁需要满足以下特点:

互斥性:同一时刻只能有一个节点可以获取到锁,其他节点需要等待。
可重入性:同一节点在获取到锁后可以再次获取锁,避免死锁的发生。
安全性:分布式锁需要保证在各种异常情况下都能正确释放锁,避免出现死锁、资源泄露等问题。
高可用性:分布式锁需要在多个节点之间实现协调,保证在节点故障时能够正确进行锁的转移和释放。
常见的分布式锁实现方式有基于数据库、基于缓存、基于ZooKeeper等。选择哪种实现方式要根据具体的业务场景和需求来决定。
现在使用redis缓存来实现简单的分布式锁。

1. 引入依赖

首先,在你的 Spring Boot 项目的 pom.xml 文件中添加 lock4j-redis-template-spring-boot-starter 和 Redis 的相关依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
  <version>2.2.7</version>
</dependency>

确保依赖的版本是最新的,可以去 Maven Central 查询最新版本。

2. 配置 Redis

在 application.properties 或 application.yml 文件中配置 Redis 的连接信息:

application.properties:


spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword

application.yml:

spring:
  redis:
    host: localhost
    port: 6379
    password: yourpassword

3. 使用分布式锁

lock4j-redis-template-spring-boot-starter 提供了简单的注解 @Lock4j,你可以在需要加锁的方法上使用该注解。下面是一个示例:


import com.baomidou.lock.annotation.Lock4j;
import org.springframework.stereotype.Service;

@Service
public class YourService {

    @Lock4j(keys = {"#arg1", "#arg2"})
    public void yourMethod(String arg1, String arg2) {
        // 需要加锁的业务逻辑
        System.out.println("Method is locked with args: " + arg1 + ", " + arg2);
        // 模拟业务处理
        try {
            Thread.sleep(5000);  // 假设业务逻辑处理需要 5 秒
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

在上述示例中,yourMethod 方法在执行时会获取一个分布式锁,锁的 key 是由方法参数 arg1 和 arg2 的值组合而成。

4. 自定义锁配置

你还可以自定义锁的配置,比如锁的过期时间和获取锁的超时时间等。这些配置可以通过在 application.properties 或 application.yml 文件中进行设置:

application.properties:

lock4j.lock.expire = 30000  # 锁的过期时间,单位毫秒
lock4j.lock.timeout = 10000 # 获取锁的超时时间,单位毫秒

application.yml:


lock4j:
  lock:
    expire: 30000  # 锁的过期时间,单位毫秒
    timeout: 10000 # 获取锁的超时时间,单位毫秒

5. 处理锁获取失败的情况

在一些情况下,如果获取锁失败,你可能需要处理这种情况。例如,可以抛出一个异常或者进行重试:


import com.baomidou.lock.annotation.Lock4j;
import com.github.yitter.lock.exception.LockException;
import org.springframework.stereotype.Service;

@Service
public class YourService {

    @Lock4j(keys = {"#arg1", "#arg2"})
    public void yourMethod(String arg1, String arg2) {
        try {
            // 需要加锁的业务逻辑
            System.out.println("Method is locked with args: " + arg1 + ", " + arg2);
            // 模拟业务处理
            Thread.sleep(5000);  // 假设业务逻辑处理需要 5 秒
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (LockException e) {
            System.err.println("Failed to acquire lock: " + e.getMessage());
            // 处理获取锁失败的情况
        }
    }
}

6. 高级用法

除了简单的注解用法,lock4j-redis-template-spring-boot-starter 还支持更高级的用法,例如:

手动管理锁:你可以通过 Lock4j 提供的 API 手动管理锁。
自定义锁策略:你可以实现自己的锁策略来满足特定需求。

7.样例


import lombok.Data;

@Data
public class CompanyInfo {

    private Long id;
    private Long gg;
}

没加锁:

 
    @GetMapping("/lockMethod")
    // @Lock4j(keys = {"#companyInfo.gg"}, acquireTimeout = 50000L, expire = 30000L)
    public String lockMethod(@RequestBody CompanyInfo companyInfo) throws InterruptedException {
        Thread.sleep(2000);
        log.info("Current tt companyInfo: " + companyInfo);
        return companyInfo.getGg().toString();
    }

输出结果:

2024-06-26 12:03:02.364  INFO 38028 --- [io-54555-exec-7] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.364  INFO 38028 --- [io-54555-exec-6] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.364  INFO 38028 --- [io-54555-exec-9] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.364  INFO 38028 --- [io-54555-exec-4] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.364  INFO 38028 --- [io-54555-exec-8] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.364  INFO 38028 --- [io-54555-exec-3] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.364  INFO 38028 --- [io-54555-exec-5] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.365  INFO 38028 --- [io-54555-exec-2] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.365  INFO 38028 --- [o-54555-exec-10] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:02.365  INFO 38028 --- [io-54555-exec-1] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:03:03.777  INFO 38028 --- [o-54555-exec-20] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.777  INFO 38028 --- [o-54555-exec-11] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.777  INFO 38028 --- [o-54555-exec-13] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.777  INFO 38028 --- [o-54555-exec-16] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.777  INFO 38028 --- [o-54555-exec-14] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.777  INFO 38028 --- [o-54555-exec-15] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.779  INFO 38028 --- [o-54555-exec-18] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.779  INFO 38028 --- [o-54555-exec-19] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.779  INFO 38028 --- [o-54555-exec-12] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:03:03.780  INFO 38028 --- [o-54555-exec-17] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)

结果得知,抢占资源

加了分布式锁:


    /**
     * 使用分布式锁演示一个方法,其主要目的是为了锁定特定的键。
     *
     * @param companyInfo 包含用于锁键信息的对象。
     * @return 公司GG值的字符串表示。
     * @throws InterruptedException 如果线程被中断。
     */
    @GetMapping("/lockMethod")
    @Lock4j(keys = {"#companyInfo.gg"}, acquireTimeout = 50000L, expire = 30000L)
    public String lockMethod(@RequestBody CompanyInfo companyInfo) throws InterruptedException {
        Thread.sleep(2000);
        log.info("Current tt companyInfo: " + companyInfo);
        return companyInfo.getGg().toString();
    }

使用压测工具apipost并发10次可以测试得到:

2024-06-26 12:01:02.754  INFO 34972 --- [o-54555-exec-26] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:03.562  INFO 34972 --- [o-54555-exec-32] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:04.841  INFO 34972 --- [io-54555-exec-6] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:05.636  INFO 34972 --- [o-54555-exec-40] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:06.890  INFO 34972 --- [io-54555-exec-4] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:07.712  INFO 34972 --- [o-54555-exec-38] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:08.946  INFO 34972 --- [io-54555-exec-7] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:09.745  INFO 34972 --- [o-54555-exec-39] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:11.015  INFO 34972 --- [o-54555-exec-12] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:11.791  INFO 34972 --- [o-54555-exec-36] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:13.067  INFO 34972 --- [o-54555-exec-30] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:13.862  INFO 34972 --- [o-54555-exec-35] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:15.108  INFO 34972 --- [o-54555-exec-18] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:15.920  INFO 34972 --- [o-54555-exec-33] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:17.157  INFO 34972 --- [o-54555-exec-11] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:17.953  INFO 34972 --- [o-54555-exec-37] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:19.228  INFO 34972 --- [o-54555-exec-16] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:20.008  INFO 34972 --- [o-54555-exec-41] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)
2024-06-26 12:01:21.266  INFO 34972 --- [o-54555-exec-29] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=1111, gg=222)
2024-06-26 12:01:22.111  INFO 34972 --- [o-54555-exec-34] c.r.R.r.controller.RedisDemoController   : Current tt companyInfo: CompanyInfo(id=44, gg=44)

由上面可以得出,加了分布式锁可以解决资源公用的问题。

总结
通过上述步骤,你可以使用 lock4j-redis-template-spring-boot-starter 快速在 Spring Boot 项目中实现基于 Redis 的分布式锁。该 starter 提供了简洁的注解方式,方便开发者在业务逻辑中使用分布式锁。同时,你还可以根据需要进行自定义配置,以满足不同的业务需求。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python特征工程 — 1.4 特征归一化方法详解

目录 1 Min-Max归一化 方法1&#xff1a;自定义的Min-Max归一化封装函数 方法2&#xff1a; scikit-learn库中的MinMaxScaler 2 Z-score归一化 方法1&#xff1a;自定义的Z-score归一化封装函数 方法2&#xff1a; scikit-learn库中的StandardScaler 3 最大值归一化 4 L…

嵌入式c语言3——自定义数据类型

结构体struct&#xff0c;共用体union 结构体中定义变量&#xff0c;首尾地址相连 对于union&#xff0c;其包含变量对起始地址相同 由于其起始地址相同&#xff0c;则改变其中某一变量值时有可能使得另一个变量值发生改变 enum 枚举&#xff0c;可以用来定义一堆整形常量构成…

AzureDataFactory Dataverse connector自动处理了分页问题(单次查询上限5000条的限制)

众所周知&#xff0c;在用fetch执行D365的查询时&#xff0c;单次的查询是5000条&#xff0c;如果超过5000条则需要自己处理分页&#xff0c;添加额外的处理逻辑&#xff0c;但在ADF中&#xff0c;Dataverse connector已经自动处理了分页&#xff0c;我们可以很简单的做个POC. …

昇思25天学习打卡营第05天 | 数据变换 Transforms

昇思25天学习打卡营第05天 | 数据变换 Transforms 文章目录 昇思25天学习打卡营第05天 | 数据变换 TransformsCommon TransformsCompose Vision TransformsText TransformPythonTokenizerLookup Lambda Transforms数据处理模式Pipeline模式Eager模式 总结打卡 通常情况下的原始…

巴图制自动化Profinet协议转Modbus协议模块连接PLC和电表通信

1、免编写Modbus轮询程序实现PLC与电表通信的方法 在智能化时代&#xff0c;工业自动控制中的PLC和电表之间的通信是一个常见的需求。传统上&#xff0c;为了使PLC与电表通信&#xff0c;通常需要编写Modbus查询程序来读取和控制数据。然而&#xff0c;使用 巴图制自动化Prof…

(十二)纹理和采样

纹理 在绘制三角形的过程中&#xff0c;将图片贴到三角形上进行显示的过程&#xff0c;就是纹理贴图的过程 uv坐标 如果如果图片尺寸和实际贴图尺寸不一致&#xff0c;就会导致像素不够用了的问题 纹理与采样 纹理对象(Texture)&#xff1a;在GPU端&#xff0c;用来以一…

安全隔离上网的有效途径:沙箱

在数字化浪潮日益汹涌的今天&#xff0c;网络安全成为了不可忽视的重要议题。沙箱技术作为一种高效的隔离机制&#xff0c;为企业和个人提供了一种在享受网络便利的同时&#xff0c;保障系统安全的解决方案。本文旨在深入探讨沙箱技术如何做到隔离上网&#xff0c;从而为用户提…

(五十二)第 8 章 动态存储管理(边界标识法)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strr…

QT创建地理信息shp文件编辑器shp_editor

空闲之余创建一个简单的矢量shp文件编辑器&#xff0c;加深对shp文件的理解。 一、启动程序 二、打开shp文件 三、显示shp文件的几何图形 四、双击右边表格中的feature&#xff0c;主窗体显示选中feature的各个节点。 五、鼠标在主窗体中选中feature的节点&#xff0c;按鼠标左…

js学习--制作选项卡

选项卡制作 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>.text_one {width: 11.4%;height: 200px…

web前端开发(概述篇)

一、概念 Web是Internet上的一种多媒体信息服务系统&#xff0c;整个系统由Web服务器、浏览器和通信协议组成。 通信协议HTTP能够传输任意类型的数据对象&#xff0c;满足Web服务器与客户之间的多媒体通信的需求。 一般来说&#xff0c;Web开发分为前端&#xff08;Front-en…

番外篇 | 手把手教你如何去更换YOLOv5的检测头为ASFF_Detect

前言:Hello大家好,我是小哥谈。自适应空间特征融合(ASFF)的主要原理旨在解决单次检测器中不同尺度特征的不一致性问题。具体来说,ASFF通过动态调整来自不同尺度特征金字塔层的特征贡献,确保每个检测对象的特征表示是一致且最优的。本文所做出的改进是将YOLOv5的检测头更换…

身边的故事(十三):阿文的故事:出现

如果他知道一件事情如果违背正常的市场规律就是骗局或者存在巨大的风险&#xff0c;比如市场正常投资回报率在5-6%已经算高回报&#xff0c;像股神巴菲特的投资回报率应该不会超过10%吧。那些说20-30%甚至更高回报率肯定是骗局。如果...哪有那么多如果&#xff0c;人生每一秒都…

从4D CT灌注成像中使用时空卷积神经网络预测急性缺血性中风的特定治疗病变结果| 文献速递-深度学习自动化疾病检查

Title 题目 Predicting treatment-specific lesion outcomes in acute ischemic stroke from 4D CT perfusion imaging using spatio-temporal convolutional neural networks 从4D CT灌注成像中使用时空卷积神经网络预测急性缺血性中风的特定治疗病变结果 01 文献速递介绍…

【电商指标详解】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本篇文章主要和大家分享一下电商行业中常见指标的详解&#xff01;存在的原因和作用&#xff01;&#xff01;&#xff01;希望对大家有所帮助。 &#x1f49e;&#x1f49e;代码是你的画…

打卡第一天

今天是参加算法训练营的第一天&#xff0c;希望我能把这个训练营坚持下来&#xff0c;希望我的算法编程题的能力有所提升&#xff0c;不再面试挂了&#xff0c;面试总是挂编程题&#xff0c;记录我leetcode刷题数量&#xff1a; 希望我通过这个训练营能够实现两份工作的无缝衔接…

Vue项目打包上线

Nginx 是一个高性能的开源HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP代理服务器。它在设计上旨在处理高并发的请求&#xff0c;是一个轻量级、高效能的Web服务器和反向代理服务器&#xff0c;广泛用于提供静态资源、负载均衡、反向代理等功能。 1、下载nginx 2、…

2024企业数据资产化及数据资产入表方案梳理

01 数据资产入表&#xff1a;是一个将组织的各类数据资产进行登记、分类、评估和管理的流程。 数据资产包括&#xff1a;客户信息、交易记录、产品数据、财务数据等。 做个比喻吧&#xff1a;数据资产入表就像是给公司的数据资产做“人口普查”—— ①找出公司有哪些数据找…

python中的文件

1.什么是文件&#xff1f; 硬盘上存储的数据都是以文件的形式来组织的~ 文件是数据在硬盘上的存储形式&#xff0c;不同的数据在硬盘上的存储形式是不同的&#xff0c; 2.文件路径 文件夹/目录。 文件夹&#xff0c;再包含文件夹的情况&#xff0c;这就是一个嵌套的关系&…

顺序表--数据结构第一关

顺序表 数据结构概念 定义&#xff1a;数据结构是计算机存储、组织数据的⽅式 根据学过C语言的基础上&#xff0c;数组是最简单的数据结构 顺序表的底层就是数组 为什么呢&#xff1f; 例子如下&#xff1a; int arr[100]{1,2,3,4,5}; //修改某一个数据&#xff1a;arr[…
最新文章