基于Redisson 实现 Redis 分布式锁

代码示例:

    @GetMapping("/testJmeter")public void testJmeter() {synchronized (this){int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"))if (stock > 0) {int realStock = stock - 1;stringRedisTemplate.opsForValue().set("stock",realStock);System.out.println("扣减成功,剩余:"+ realStock);} else {System.out.println("扣减失败");}}}

问题:上面这种方法在单台Tomcat 服务中,可以实现 防止超卖问题,可是在实际项目开发中,我们部署项目一般不会只使用一台服务器 部署,一般都是多台服务器 通过 Nginx 实现服务代理,负载均衡。 这样简单使用 synchronized 是不可取的!!!

简单优化方法:

    @GetMapping("/testJmeter")public void testJmeter() {try {String lockKey = "lockKey";Boolean  result = stringRedisTempalte.opsForValue.setIfAbsent(lockKey,"zhuzhe");if (!result) {return "错误";} int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"))if (stock > 0) {int realStock = stock - 1;stringRedisTemplate.opsForValue().set("stock",realStock);System.out.println("扣减成功,剩余:"+ realStock);} else {System.out.println("扣减失败");}} finaly{stringRedisTempalte.delete(lockKey);}}

问题:但是上述容易出现,某台机器突然宕机的现象,就无法走到finally 中去释放锁了。导师redis 中 的锁还没有释放。别的机器就无法获得锁了。 就会出现死锁问题。

优化方法:

可以实现对 给这把锁加上一个过期时间

    @GetMapping("/testJmeter")public void testJmeter() {try {String lockKey = "lockKey";Boolean  result = stringRedisTempalte.opsForValue
.setIfAbsent(lockKey,"zhuzhe",10,TimeUnit.SECONDS); // 设置过期时间if (!result) {return "错误";} int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"))if (stock > 0) {int realStock = stock - 1;stringRedisTemplate.opsForValue().set("stock",realStock);System.out.println("扣减成功,剩余:"+ realStock);} else {System.out.println("扣减失败");}} finaly{stringRedisTempalte.delete(lockKey);}}

 依然会有点问题--->失效时间不好设置,其中业务逻辑出现 SQL 慢查询导致代码执行时间长,在高并发情况下,会出现删 错锁的情况。A服务把 B服务中的锁 删除了。

优化方法:

每个线程都生成一个唯一id

    @GetMapping("/testJmeter")public void testJmeter() {try {String lockKey = "lockKey";String clientId = UUID.randomUUID.totring();Boolean  result = stringRedisTempalte.opsForValue
.setIfAbsent(lockKey ,clientId ,10,TimeUnit.SECONDS); // 设置过期时间if (!result) {return "错误";} int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"))if (stock > 0) {int realStock = stock - 1;stringRedisTemplate.opsForValue().set("stock",realStock);System.out.println("扣减成功,剩余:"+ realStock);} else {System.out.println("扣减失败");}} finaly{if (clientId.equals(stringRedisTempalte.opsForValue.getLockKey)){stringRedisTempalte.delete(lockKey);}}}

注意:其实还可以使用,创建一个定时任务,每10s 检查这个主线程的锁是否过期,如果快过期了,任务还没有结束,在延长30s.

最终解决方法:

引入 Redission 依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.6.5</version>
</dependency>

配置:

@Configuration
public class RedissonConfig {@Value("${spring.redis.host}")private String address;@Value("${spring.redis.port}")private String port;@Value("${spring.redis.password}")private String password;@Beanpublic RedissonClient redissonClient() {Config config = new Config();//此处为单机模式  (注:有多种模式)config.useSingleServer().setAddress("redis://" + address + ":"+port).setPassword(password).setTimeout(10000).setRetryAttempts(5).setRetryInterval(2000).setConnectionPoolSize(64).setConnectionMinimumIdleSize(24)// 保持连接活动.setKeepAlive(true)// 发送PING命令的间隔时间;.setPingConnectionInterval(30000);return Redisson.create(config);}
}

 代码示例:

@Rescourse
private Redisson redisson;@GetMapping("/testJmeter")public void testJmeter() {try {String lockKey = "lockKey";String clientId = UUID.randomUUID.totring();//获取锁Rlock redissonLock = redisson.getLock(lockkey);//Boolean  result = stringRedisTempalte.opsForValue
.setIfAbsent(lockKey ,clientId ,10,TimeUnit.SECONDS); // 设置过期时间//if (!result) {//  return "错误";// } //加锁redissonLock.lock()int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"))if (stock > 0) {int realStock = stock - 1;stringRedisTemplate.opsForValue().set("stock",realStock);System.out.println("扣减成功,剩余:"+ realStock);} else {System.out.println("扣减失败");}} finaly{//释放锁redissonLock.unlock()// if (clientId.equals(stringRedisTempalte.opsForValue.getLockKey)){//stringRedisTempalte.delete(lockKey);}}}

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

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

相关文章

盘点:流媒体视频流协议与EasyCVR视频监控技术的深度融合

随着科技的不断进步&#xff0c;视频监控技术已经渗透到了社会的各个角落&#xff0c;从公共安全到企业运营&#xff0c;再到家庭安全&#xff0c;其应用范围日益广泛。而视频流格式作为视频监控技术的核心要素之一&#xff0c;其选择和应用对于确保视频传输的流畅性、清晰度和…

Python爬虫教程第3篇-解决使用reqeusts遇到的ProxyError异常

起因 问题出现在windows电脑上&#xff0c;我用mac执行程序的时候并不会报错&#xff0c;但是如果在windows上的时候&#xff0c;大部分windows电脑会报错&#xff0c;而有些版本低的windows电脑又不会报错。 异常栈信息 HTTPSConnectionPool, Cannot connect to proxy, no …

基于SpringBoot的校园疫情防控系统

你好&#xff0c;我是专注于计算机科学与技术的研究者。如果你对我的工作感兴趣或有任何问题&#xff0c;欢迎随时联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架&#xff0c;B/S架构 工具&#xff1a;Eclipse&#xff0c;Mav…

2024中国互联网大会 | 中国电信携手产业链伙伴推动低空经济行业创新与发展

低空经济是指以民用有人驾驶和无人驾驶航空器在低空空域内的各类飞行活动为牵引&#xff0c;辐射带动相关领域融合发展的综合经济形态。2024年全国两会&#xff0c;“低空经济”首次写入国务院政府工作报告。 赛迪顾问在《中国低空经济发展研究报告&#xff08;2024&#xff09…

【Linux】docker和docker-compose 区别是什么

Docker 和 Docker Compose 是用于容器化应用的工具,它们在开发、部署和管理容器化应用程序时有不同的作用。以下是对它们的简要介绍和功能描述: Docker 定义: Docker 是一个开源的平台,允许开发者自动化地部署、扩展和管理应用程序容器。容器是一种轻量级、可移植、独立的软…

详解C#委托与事件

在C#中&#xff0c;委托是一种引用类型的数据类型&#xff0c;允许我们封装方法的引用。通过使用委托&#xff0c;我们可以将方法作为参数传递给其他方法&#xff0c;或者将多个方法组合在一起&#xff0c;从而实现更灵活的编程模式。委托类似于函数指针&#xff0c;但提供了类…

Redis的一个典型应用

1.redis服务器与python编程环境 #install server sudo apt update sudo apt install redis-server #install python api pip install redis --timeout 200 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com 1.1 测试代码 # 创建Redis客户端实例…

树状数组(Binary Indexed Tree, BIT)

树状数组&#xff08;Binary Indexed Tree, BIT&#xff09; 树状数组&#xff08;Binary Indexed Tree, BIT&#xff09;&#xff0c;也称为 Fenwick Tree&#xff0c;是一种用于高效处理数组前缀和查询和单点更新的数据结构。它能够在 (O(\log n)) 时间内完成单点更新和前缀…

python作业二

# 二进制转化为十进制 num input("num:")def binaryToDecimal(binaryString):he 0length len(binaryString)for i in range(length):he int(binaryString[i]) * 2 ** (length - i - 1)return heprint(binaryToDecimal(num))代码运行如下&#xff1a; import math…

特种设备管理为什么这么难?为何它是安全生产的重中之重?

随着工业化进程的加速和科技水平的不断提升&#xff0c;特种设备作为工业生产、公共服务和基础设施建设中的关键要素&#xff0c;其应用范围日益广泛&#xff0c;从大型压力容器、锅炉、电梯、叉车到压力管道、客运索道等&#xff0c;无一不渗透于我们日常生活的方方面面。然而…

【qt】QTcpSocket相关的信号

QTcpSocket可以在这里找到相关的信号 进行信号槽的关联 connect():这个信号在connectToHost()被调用并且连接已经成功建立之后发出 disconnected():该信号在套接字断开连接时发出 stateChanged(QAbstractSocket::SocketState socketState):每当QAbstractSocket的状态发生变化…

【若依前后端分离】通过输入用户编号自动带出部门名称(部门树)

一、部门树 使用 <treeselect v-model"form.deptId" :options"deptOptions" :show-count"true" placeholder"请选择归属部门"/> <el-col :span"12"><el-form-item label"归属部门" prop"dept…

音视频开发—使用FFmpeg从纯H264码流中提取图片 C语言实现

文章目录 1.H264码流文件解码流程关键流程详细解码流程详细步骤解析 2.JPEG编码流程详细编码流程详细步骤解析 3.完整示例代码4.效果展示 从纯H.264码流中提取图片的过程包括解码和JPEG编码两个主要步骤&#xff0c;以下是详细阐述 1.H264码流文件解码流程 关键流程 查找编解…

go语言处理特定格式的时间 例如打印出来2024-07-12 12:22:22 -2024-07-12 12:52:22

在Go语言中&#xff0c;你可以使用time包来创建、操作和格式化时间。要打印出两个特定时间&#xff08;例如开始时间和结束时间&#xff09;的字符串表示&#xff0c;并且格式化为YYYY-MM-DD HH:MM:SS这样的形式&#xff0c;你可以使用time.Format方法。 以下是一个例子&#x…

敏捷开发笔记(第10章节)--Liskov原则(LSP)

目录 1&#xff1a;PDF上传链接 10.1 Liskov替换原则&#xff08;LSP&#xff09; 10.2 一个违反LSP的简单例子 10.6 启发式规则和习惯用法 10.7 结论 1&#xff1a;PDF上传链接 【免费】敏捷软件开发(原则模式与实践)资源-CSDN文库 OCP背后的主要机制是抽象(abstraction…

group 与查询字段

需求 每周周一&#xff0c;统计菜单在过去一周&#xff0c;点击次数&#xff0c;和点击人数&#xff08;同一个人访问多次按一次计算&#xff09; 表及数据 日志表 CREATE TABLE t_data_log ( id varchar(50) NOT NULL COMMENT 主键id, operation_object varchar(500) DE…

【D3.js in Action 3 精译】1.3 D3 视角下的数据可视化最佳实践(下)

当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介 ✔️ 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知 1.2.1 HTML 与 DOM1.2.2 SVG - 可缩放矢量图形1.2.3 Canvas 与 WebGL1.2.4 CSS1.2.5 JavaScript1.2.6 Node 与 JavaScript 框架1.2.7 Observable 记事…

python工作中遇到的坑

1. 字典拷贝 有些场景下&#xff0c;需要对字典拷贝一个副本。这个副本用于保存原始数据&#xff0c;然后原来的字典去参与其他运算&#xff0c;或者作为参数传递给一些函数。 例如&#xff0c; >>> dict_a {"name": "John", "address&q…

我的世界1.21多种服务端开服教程,原版/Forge/Fabric/Paper/Mohist...,Minecraft开服教程

Minecraft&#xff08;MC&#xff09;1.21版多种服务端开服教程&#xff0c;我的世界1.21服务器搭建教程&#xff0c;MC原版/Forge/Fabric/Paper/Mohist服务端搭建教程&#xff0c;我的世界MOD/插件服开服教程。 本教程使用 Linux系统MCSManager 面板来搭建Minecraft服务器。 …

人工智能行业应用-垃圾识别一

垃圾识别应用主要体现在AI图像垃圾识别技术上&#xff0c;这是一种基于人工智能和计算机视觉技术的图像处理技术&#xff0c;广泛应用于各个领域以提高垃圾处理的效率和准确性。 1、垃圾识别效果图 2 垃圾识别任务分析 综合利用Python语言、Qt开发模块&#xff0c;OpenCV开发模…