使用 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: localhostport: 6379password: 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.rhkb.cn/news/367506.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django 一对一关系

作用&#xff1a; 两个数据库表建立外键关系当外键表的数据被删除时&#xff0c;主表的数据也会一并删除。 1&#xff0c;添加表模型 Test/app8/views.pyfrom django.db import modelsclass User(models.Model):username models.CharField(max_length50, uniqueTrue)email …

【C语言】学生管理系统:完整模拟与实现

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 &#x1f525;引言 本篇文章为修改了在校期间实训报告&#xff0c;使用C…

【网络架构】lvs集群

目录 一、集群与分布式 1.1 集群介绍 1.2 分布式系统 1.3 集群设计原则 二、LVS 2.1 lvs工作原理 2.2 lvs集群体系架构 ​编辑 2.3 lvs功能及组织架构 2.4 lvs集群类型中术语 三、LVS工作模式和命令 3.1 lvs集群的工作模式 3.1.1 lvs的nat模式 3.1.2 lvs的dr模式 …

为什么有些人思考得多,决策反而不好?避免过度拟合的终极指南:决策高手的秘密:灰度认知,黑白决策

在决策过程中&#xff0c;过度关注细节可能导致决策效果不佳&#xff0c;这被称为“过度拟合”。为了避免这种情况&#xff0c;我们需要进行“灰度认知&#xff0c;黑白决策”&#xff0c;即接受不确定性&#xff0c;关注整体趋势&#xff0c;设定明确目标&#xff0c;简化选择…

【JD-GUI】MacOS 中使用Java反编译工具JD-GUI

希望文章能给到你启发和灵感&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏 支持一下博主吧&#xff5e; 阅读指南 开篇说明概念理解一、基础环境说明1.1 硬件环境1.2 软件环境 二、下载与安装2.1 选择对应版本2.2 解压运行排除异常&#xff1a;2.3 关于…

Geotools系列说明之LineString仿高德航路截取说明

需求分析 我们在做webgl的时候经常会遇到这样的需求&#xff0c;计算给定航路的拥堵情况&#xff0c;不同的拥堵显示不同的颜色&#xff0c;航路截取计算等等。基于这类问题统一都可以使用LineString进行处理 实现思路 如上图所示&#xff0c;航路是几个关键的点然后练成线&a…

05 docker 镜像

目录 1. 镜像 2. 联合文件系统 3. docker镜像加载原理 4. 镜像分层 镜像分层的优势 5. 容器层 1. 镜像 镜像是一种轻量级、可执行的独立软件包&#xff0c;它包含运行某个软件所需的所有内容&#xff0c;我们把应用程序和配置依赖打包好行程一个可交付的运行环境&#xf…

监控平台zabbix对接grafana

目录 1.安装grafana并启动 2.浏览器访问 3.导入zabbix数据&#xff0c;对接grafana 4.如何导入模板 5.使用zabbix监控nginx并发量连接数 5.1 修改nginx配置 5.2 编写监控数据脚本 5.3 设置键值 5.4 在zabbix web端完成自定义监控项 5.5 连接到grafana 以上一篇博客&l…

Python 生成Md文件带超链 和 PDF文件 带分页显示内容

software.md # -*- coding: utf-8 -*- import os f open("software.md", "w", encoding"utf-8") f.write(内部测试版2024 MD版\n) for root, dirs, files in os.walk(path): dax os.path.basename(root)if dax "":print("空白…

基于YOLOv9的PCB板缺陷检测

数据集 PCB缺陷检测&#xff0c;我们直接采用北京大学智能机器人开放实验室数据提供的数据集&#xff0c; 共六类缺陷 漏孔、鼠咬、开路、短路、杂散、杂铜 已经对数据进行了数据增强处理&#xff0c;同时按照YOLO格式配置好&#xff0c;数据内容如下 模型训练 ​ 采用YOLO…

StarRocks 3.3 重磅发布,Lakehouse 架构发展进入快车道!

StarRocks 3.3 的发布标志着 Lakehouse 架构在数据分析领域迈向了一个新的高度。作为下一代 Lakehouse 架构的代表&#xff0c;StarRocks 3.3 在稳定性、计算性能、缓存设计、物化视图、存储优化和 Lakehouse 生态系统等方面进行了全方位的优化和创新。本文将逐一介绍 StarRock…

如何在 SQL 中删除一条记录?

如何在 SQL 中删除一条记录&#xff1f; 在 SQL 中&#xff0c;您可以使用DELETE查询和WHERE子句删除表中的一条记录。在本文中&#xff0c;我将向您介绍如何使用DELETE查询和WHERE子句删除记录。我还将向您展示如何一次从表中删除多条记录 如何在 SQL 中使用 DELETE 这是使…

ctfshow sql注入 web234--web241

web234 $sql "update ctfshow_user set pass {$password} where username {$username};";这里被过滤了&#xff0c;所以我们用\转义使得变为普通字符 $sql "update ctfshow_user set pass \ where username {$username};";那么这里的话 pass\ where…

踩坑:Unity导出WebGL发布到手机上竖屏时强制显示横屏

具体的适配问题 公司的项目需要将游戏导出WebGL 发布到Web平台 本以为是个很简单的事情 谁知道却被个横竖屏适配搞的头晕 毕竟只有大学浅浅的学了下HTML这门语言 出来工作后基本上都是在跟C# Lua打交道 言归正传 看看具体问题吧 游戏如果从横屏进入 基本上不会有什么适配问题…

预处理详解

1.预定义符号 C语言设置了一些预定义符号&#xff0c;可以直接使用&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI C&…

在Clion使用CubeMX Stm32的步骤

Step1 准备软件&#xff0c;安装环境&#xff1a; 1. cubemx v6.5.0&#xff08;可以兼容以前版本的project&#xff09; https://www.st.com.cn/zh/development-tools/stm32cubemx.html STM32CubeMX 默认安装目录, 6.5版本可以兼容老版本 C:\Program Files\STMicroelectroni…

SpringMVC常见的注解

一、Spring MVC Spring Web MVC是基于ServletAPI构建的原始web 框架&#xff0c;一开始就包含在Spring 框架中&#xff0c;通常被称为“Spring MVC”。 1.MVC 是什么&#xff1f; MVC(Model、View、Controller&#xff09;是软件工程中的一种软件架构设计模型。它把软件系统分…

Vision Transformer论文阅读笔记

目录 An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale -- Vision Transformer摘要Introduction—简介RELATED WORK—相关工作METHOD—方法VISION TRANSFORMER (VIT)—视觉Transformer(ViT) 分析与评估PRE-TRAINING DATA REQUIREMENTS—预训练数据…

战略流程-麦肯锡企业数字化业务变革成熟度评估模型及案例深度解析

一、企业变革成熟度评估模型 企业变革成熟度诊断模型是一种评估工具&#xff0c;用于全面扫描和评估企业在变革转型过程中的能力水平。该模型通过一系列量化指标和定性分析&#xff0c;对企业在不同变革领域的成熟度进行评分&#xff0c;从而帮助企业识别在变革过程中的优势和…

llm学习-3(向量数据库的使用)

1&#xff1a;数据读取和加载 接着上面的常规操作 加载环境变量---》获取所有路径---》加载文档---》切分文档 代码如下&#xff1a; import os from dotenv import load_dotenv, find_dotenvload_dotenv(find_dotenv()) # 获取folder_path下所有文件路径&#xff0c;储存在…