SpringBoot与Redisson整合,用注解方式解决分布式锁的使用问题

文章引用:https://mp.weixin.qq.com/s/XgdKE2rBKL0-nFk2NJPuyg

一、单个服务

1.代码

该接口的作用是累加一个值,访问一次该值加1

@RestController
public class LockController {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@GetMapping("/increment")public String increment() {int counter = Integer.parseInt(stringRedisTemplate.opsForValue().get("count"));counter++;System.out.println("当前结果:" + counter);stringRedisTemplate.opsForValue().set("count", String.valueOf(counter));return "结果:" + counter;}
}

2.jmeter工具压测

用100个线程,每个线程访问100次去压测,理论上该值最后应该返回10000
在这里插入图片描述

3.结果

在这里插入图片描述
在这里插入图片描述

发生了线程安全问题,部分请求返回结果相同

4.解决办法:加锁

@RestController
public class LockController {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@GetMapping("/increment")public synchronized String increment() {int counter = Integer.parseInt(stringRedisTemplate.opsForValue().get("count"));counter++;System.out.println("当前结果:" + counter);stringRedisTemplate.opsForValue().set("count", String.valueOf(counter));return "结果:" + counter;}
}

在这里插入图片描述
在非集群模式下,简单上锁能解决线程安全问题。

二、集群模式

代码相同,idea启动两个相同的服务

1.启动两个服务

在这里插入图片描述

2.nginx配置负载均衡

upstream backend {# 定义后端服务器列表server localhost:8081;server localhost:8082;}server {listen 8080;location / {# 将请求代理到后端服务器proxy_pass http://backend;}}

3.jmeter工具压测

用100个线程,每个线程访问100次去压测,理论上该值最后应该返回10000
在这里插入图片描述
在这里插入图片描述
还是出了线程安全问题,synchronized只能锁住单个服务

三、SpringBoot整合Redisson(注解方式)

1.依赖和配置文件

<dependencies><!-- Spring Boot Starter for Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--         Redisson Dependency--><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.17.6</version><!-- 请根据需要调整版本 --></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.10</version></dependency></dependencies>
spring:
redis:host:localhostport:6379# Redisson configuration
redisson:single-server-address:redis://@localhost:6379

2.代码

注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DistributedLock {String lockName();
}

切面

@Aspect
@Component
public class DistributedLockAspect {@Autowiredprivate RedissonClient redissonClient;@Around("@annotation(DistributedLock)")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {MethodSignature signature = (MethodSignature) joinPoint.getSignature();DistributedLock annotation = signature.getMethod().getAnnotation(DistributedLock.class);String lockName = annotation.lockName();RLock lock = redissonClient.getLock(lockName);try {// 尝试获取锁,最多等待10秒,持有锁的时间为30秒if (!lock.tryLock(10, 30, TimeUnit.SECONDS)) {throw new RuntimeException("Failed to acquire lock.");}return joinPoint.proceed();} finally {// 确保在任何情况下都能释放锁if (lock.isHeldByCurrentThread()) {lock.unlock();}}}
}

接口

@RestController
public class LockController {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@GetMapping("/increment")@DistributedLock(lockName = "counterLock")public String increment() {int counter = Integer.parseInt(stringRedisTemplate.opsForValue().get("count"));counter++;System.out.println("当前结果:" + counter);stringRedisTemplate.opsForValue().set("count", String.valueOf(counter));return "结果:" + counter;}
}

3.结果

实现了分布式锁,俩个服务依次接受了所有请求,并无重复值
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

SpringBoot 统一功能处理

目录 1. 拦截器 1.1 什么是拦截器 1.2 定义拦截器 1.3 注册拦截器 1.3.1 拦截路径 1.4 登录校验 - 拦截器 1.4.1 定义拦截器 1.4.2 注册拦截器 1.4.3 前端代码 1.5 DisPatchServlet 底层源码解析 2. 统一结果返回格式 2.1 ResponseBodyAdvice 2.1.1 存在问题1 - 原本…

电机控制常见面试问题(十八)

文章目录 一.电机控制高级拓扑结构1.LLC 二.谈谈电压器饱和后果三.电压器绕组连接方式的影响四.有源逆变的条件 一.电机控制高级拓扑结构 1.LLC LLC是什么&#xff1f;—— 一个会"变魔术"的电源盒子 想象你有一个魔法盒子&#xff0c;能把电池的电压变大或变小&…

如何解决用户名文件夹是中文导致的识别不到路径,获取不到ssh密匙

如果你不想更改你的文件夹用户名导致之前配置的环境变量及相关软件失效&#xff0c;那么只需要指定自定义路径生成密钥 完整解决方案 1. 设置一个简单的 HOME 路径 由于你的用户名包含中文字符&#xff0c;导致默认路径 无法正确解析。我们可以通过修改 HOME 环境变量&#…

Python入门基础

python基础类型转换 str()与int()类型转换 name 张三 age 20 print(type(name),type(age))print(我叫name 今年&#xff0c; str(age)岁 )a10 b198.8 cFalse print(type(a),type(b),type(c)) print(str(a),str(b),str(c))s1 128 f198.7 s276.77 ffTrue s3hello print(type(s…

GithubPages+自定义域名+Cloudfare加速+浏览器收录(2025最新排坑)

前言 最近刷到一个小视频&#xff0c;讲述了选择域名选择的三宗罪&#xff0c;分别是 不要使用 .net&#xff0c;因为它价格贵&#xff0c;但是在顶级域名中的 SEO 效果却不是很好&#xff0c;也就是性价比很低不要使用 .cn&#xff0c;因为国外访问该网站可能会很慢&#xf…

监控IP,网站将异常情况通过飞书机器人发至指定群内

界面如下&#xff0c;丑是丑了点&#xff0c;但主打一个实用。 主要就是通过ping&#xff0c;就是一直在ping&#xff0c;当不通的时候&#xff0c;就根据你设置的报警时间&#xff0c;主要是利用飞书机器人来给飞书指定群里发异常信息报警。 直接上代码 import subprocess i…

2018扬州大学876农业机械学概论填空名词解释简答

2018 7.全喂入式脱粒机根据脱粒装置的工作特点&#xff0c;主要通过脱粒部件的结构与作用方式区分。其中&#xff0c;纹杆式脱粒装置依靠纹杆的击打、搓擦作用脱粒&#xff1b;弓齿式脱粒装置则通过弓齿的梳刷、打击实现脱粒。 8.主犁体作为犁具核心部件&#xff0c;各部分分…

C++KNN 算法应用痛点:从受噪声干扰到精准预测的突破

在机器学习算法家族中,K近邻(K-Nearest Neighbors,KNN)算法以其概念简单却又异常强大的特性脱颖而出。作为一名长期从事高性能计算优化的C++专家,我始终对KNN算法情有独钟。为何如此?想象一下,在数十种复杂的算法中,有一种算法能够不需要繁琐的数学推导,仅凭直觉就能理…

996引擎-接口测试:消息Tips

996引擎-接口测试:消息Tips 发送视野内广播消息 sendrefluamsg发送聊天框消息 sendmsg发送地图消息 sendmapmsg打印消息到控制台 release_print发送自定义颜色的文字信息 guildnoticemsg测试NPC参考资料发送视野内广播消息 sendrefluamsg function npc_test_onclick1(player)-…

2025年上软考——【系统架构设计师】考前60天冲刺学习指南!!!

距离2025上半年“系统架构设计师”考试已经只剩两个月了&#xff0c;还没有开始备考的小伙伴赶紧行动起来。为了帮助大家更好的冲刺学习&#xff0c;特此提供一份考前60天学习指南。本指南包括考情分析、学习规划、冲刺攻略三个部分&#xff0c;可以参考此指南进行最后的复习要…

Redis 服务搭建

&#x1f4a2;欢迎来到张翊尘的开源技术站 &#x1f4a5;开源如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 Redis 服务搭建源代码编译安装获取源码安装依赖Ub…

【AI神经网络】深度神经网络(DNN)技术解析:从原理到实践

引言 深度神经网络&#xff08;Deep Neural Network, DNN&#xff09;作为人工智能领域的核心技术&#xff0c;近年来在计算机视觉、自然语言处理、医疗诊断等领域取得了突破性进展。与传统机器学习模型相比&#xff0c;DNN通过多层非线性变换自动提取数据特征&#xff0c;解决…

FPGA中串行执行方式之流水线(Pipeline)

FPGA中串行执行方式之流水线(Pipeline) 在FPGA设计中,​流水线(Pipeline)​ 是一种常见的优化技术,用于提高系统的吞吐量和性能。流水线通过将复杂的逻辑分解为多个阶段,每个阶段在一个时钟周期内完成一部分工作,并将中间结果传递到下一阶段。这种方式可以显著提高时钟…

【机器学习】什么是决策树?

什么是决策树&#xff1f; 决策树是一种用于分类和回归问题的模型。它通过一系列的“决策”将数据逐步分裂&#xff0c;最终得出预测结果。可以把它看作是一个“树”&#xff0c;每个节点表示一个特征的判断&#xff0c;而每个分支代表了可能的判断结果&#xff0c;最终的叶子…

ZW3D二次开发_非模板表单_控件_添加回调

ZW3D的非模板表单的控件即“ZW3D Widgets”下的控件&#xff0c;常用的如“ZsCc::ComboBox”,"Zscc::ListWidget","ZsCc::MatrixPushButtons","Zscc::TableWidget"和"ZsCc::TreeView"等&#xff0c;使用它们时&#xff0c;ZW3D在内部实…

git 合并多次提交 commit

在工作中&#xff0c;有时候在反复修改代码中&#xff08;比如处理MR的检视意见&#xff0c;或者为了推送到测试环境&#xff0c;先 commit到自己的远程分支上&#xff09;不免会有多次 commit&#xff0c;这样发起 MR 的时候&#xff0c;就会有一堆 commit 信息&#xff0c;看…

【golang学习之旅】使用VScode安装配置Go开发环境

1. 下载并安装Go 1.1 下载地址1.2 选择版本并下载1.3 安装目录1.4 验证是否安装成功 2. 配置环境变量 2.1 配置步骤2.2 GO部分环境变量说明 3. 下载或更新 Vscode 3.1 下载地址3.2 安装步骤 4. 为Go开发配置VScode 1. 下载并安装Go 1.1 下载地址 https://studygolang.com/dl…

制作PaddleOCR/PaddleHub的Docker镜像

背景 在落地RAG知识库过程中&#xff0c;遇到了图文识别、图片表格内容识别的需求。但那时&#xff08;2024年4月&#xff09;各开源RAG项目还没有集成成熟的解决方案&#xff0c;经调研我选择了百度开源的PaddleOCR。支持国产&#xff01; 概念梳理 PaddleOCR 百度飞桨的OCR…

Mysql基本查询(上)

&#x1f3dd;️专栏&#xff1a;Mysql_猫咪-9527的博客-CSDN博客 &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 1. 创建&#xff08;create&#xff09; 全列插入 省略into插入 插入…

[工控机安全] 使用DriverView快速排查不可信第三方驱动(附详细图文教程)

导语&#xff1a; 在工业控制领域&#xff0c;设备驱动程序的安全性至关重要。第三方驱动可能存在兼容性问题、安全漏洞甚至恶意代码&#xff0c;威胁设备稳定运行。本文将手把手教你使用 DriverView工具&#xff0c;高效完成工控机驱动安全检查&#xff0c;精准识别可疑驱动&a…