当前位置: 首页 > news >正文

【分布式锁】Redission实现分布式锁

接着上一节,我们遇到了超卖的问题,并通过Redis实现分布式锁,进行了解决。本节 我将换一种方式实现分布式锁。

前提:
nginx、redis、nacos
模块1:
provider-and-consumer 端口 8023
模块2
rabbitmq-consumer 端口 8021

添加依赖

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

业务代码

模块1代码 RedisTestController.java

package com.atguigu.gulimall.providerconsumer.controller;import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.UUID;
import java.util.concurrent.TimeUnit;/*** @author: jd* @create: 2024-07-08*/
@RestController
@RequestMapping("/test")
@Slf4j
public class RedisTestController {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate RedissonClient redissonClient;@GetMapping("/RedissonLock")public String  deductStockByRedisson(){//写死一个固定商品ID,作为我们被秒杀的商品String lockKey="lock:product:102";//获取锁对象RLock lock = redissonClient.getLock(lockKey);//加锁,使用lock方法,锁将会自动续命lock.lock();try{//获取当前库存String stock1 = stringRedisTemplate.opsForValue().get("stock");if(stock1==null){System.out.println("秒杀未开始,请等开始后操作下单");return "end";}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("扣减库存失败,库存不足");}}finally {if(lock.isLocked()&&lock.isHeldByCurrentThread()){//释放分布式锁lock.unlock();System.out.println("分布式锁释放"); //解锁}}return "end";}}

模块2代码 RedisTestController.java

package com.atguigu.gulimall.rabbitmqconsumer.controller;import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.UUID;
import java.util.concurrent.TimeUnit;/**** 和provider-and-consumer 这两个服务中都有这个RedisTestController,用来模拟两个不同的服务* @author: jd* @create: 2024-07-08*/
@RestController
@RequestMapping("/test")
@Slf4j
public class RedisTestController {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate RedissonClient redissonClient;@GetMapping("/RedissonLock")public String  deductStockByRedisson(){//写死一个固定商品ID,作为我们被秒杀的商品String lockKey="lock:product:102";//获取锁对象RLock lock = redissonClient.getLock(lockKey);//加锁,使用lock方法,锁将会自动续命lock.lock();try{//获取当前库存String stock1 = stringRedisTemplate.opsForValue().get("stock");if(stock1==null){System.out.println("秒杀未开始,请等开始后操作下单");return "end";}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("扣减库存失败,库存不足");}}finally {if(lock.isLocked()&&lock.isHeldByCurrentThread()){//释放分布式锁lock.unlock();System.out.println("分布式锁释放"); //解锁}}return "end";}}

测试结果:
单次请求,我发送两次,结果:
在这里插入图片描述

在这里插入图片描述

第二次:

在这里插入图片描述

成功扣减。

并发情况模拟:
当前库存数
在这里插入图片描述
压测:
在这里插入图片描述
并发压测结果:
8023模块

扣减成功,剩余的库存为:83
分布式锁释放
扣减成功,剩余的库存为:81
分布式锁释放
扣减成功,剩余的库存为:80
分布式锁释放
扣减成功,剩余的库存为:78
分布式锁释放
扣减成功,剩余的库存为:76
分布式锁释放
扣减成功,剩余的库存为:75
分布式锁释放
扣减成功,剩余的库存为:72
分布式锁释放
扣减成功,剩余的库存为:68
分布式锁释放
扣减成功,剩余的库存为:66
分布式锁释放
扣减成功,剩余的库存为:64
分布式锁释放
扣减成功,剩余的库存为:62
分布式锁释放
扣减成功,剩余的库存为:60
分布式锁释放
扣减成功,剩余的库存为:58
分布式锁释放
扣减成功,剩余的库存为:56
分布式锁释放
扣减成功,剩余的库存为:54
分布式锁释放
扣减成功,剩余的库存为:52
分布式锁释放
扣减成功,剩余的库存为:50
分布式锁释放
扣减成功,剩余的库存为:48
分布式锁释放
扣减成功,剩余的库存为:46
分布式锁释放
扣减成功,剩余的库存为:44
分布式锁释放
扣减成功,剩余的库存为:42
分布式锁释放
扣减成功,剩余的库存为:40
分布式锁释放
扣减成功,剩余的库存为:38
分布式锁释放
扣减成功,剩余的库存为:36
分布式锁释放
扣减成功,剩余的库存为:34
分布式锁释放
扣减成功,剩余的库存为:32
分布式锁释放
扣减成功,剩余的库存为:30
分布式锁释放
扣减成功,剩余的库存为:28
分布式锁释放
扣减成功,剩余的库存为:26
分布式锁释放
扣减成功,剩余的库存为:24
分布式锁释放
扣减成功,剩余的库存为:22
分布式锁释放
扣减成功,剩余的库存为:20
分布式锁释放
扣减成功,剩余的库存为:18
分布式锁释放
扣减成功,剩余的库存为:16
分布式锁释放
扣减成功,剩余的库存为:14
分布式锁释放
扣减成功,剩余的库存为:12
分布式锁释放
扣减成功,剩余的库存为:10
分布式锁释放
扣减成功,剩余的库存为:8
分布式锁释放
扣减成功,剩余的库存为:6
分布式锁释放
扣减成功,剩余的库存为:4
分布式锁释放
扣减成功,剩余的库存为:2
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放

8021模块日志

扣减成功,剩余的库存为:82
分布式锁释放
扣减成功,剩余的库存为:79
分布式锁释放
扣减成功,剩余的库存为:77
分布式锁释放
扣减成功,剩余的库存为:74
分布式锁释放
扣减成功,剩余的库存为:73
分布式锁释放
扣减成功,剩余的库存为:71
分布式锁释放
扣减成功,剩余的库存为:70
分布式锁释放
扣减成功,剩余的库存为:69
分布式锁释放
扣减成功,剩余的库存为:67
分布式锁释放
扣减成功,剩余的库存为:65
分布式锁释放
扣减成功,剩余的库存为:63
分布式锁释放
扣减成功,剩余的库存为:61
分布式锁释放
扣减成功,剩余的库存为:59
分布式锁释放
扣减成功,剩余的库存为:57
分布式锁释放
扣减成功,剩余的库存为:55
分布式锁释放
扣减成功,剩余的库存为:53
分布式锁释放
扣减成功,剩余的库存为:51
分布式锁释放
扣减成功,剩余的库存为:49
分布式锁释放
扣减成功,剩余的库存为:47
分布式锁释放
扣减成功,剩余的库存为:45
分布式锁释放
扣减成功,剩余的库存为:43
分布式锁释放
扣减成功,剩余的库存为:41
分布式锁释放
扣减成功,剩余的库存为:39
分布式锁释放
扣减成功,剩余的库存为:37
分布式锁释放
扣减成功,剩余的库存为:35
分布式锁释放
扣减成功,剩余的库存为:33
分布式锁释放
扣减成功,剩余的库存为:31
分布式锁释放
扣减成功,剩余的库存为:29
分布式锁释放
扣减成功,剩余的库存为:27
分布式锁释放
扣减成功,剩余的库存为:25
分布式锁释放
扣减成功,剩余的库存为:23
分布式锁释放
扣减成功,剩余的库存为:21
分布式锁释放
扣减成功,剩余的库存为:19
分布式锁释放
扣减成功,剩余的库存为:17
分布式锁释放
扣减成功,剩余的库存为:15
分布式锁释放
扣减成功,剩余的库存为:13
分布式锁释放
扣减成功,剩余的库存为:11
分布式锁释放
扣减成功,剩余的库存为:9
分布式锁释放
扣减成功,剩余的库存为:7
分布式锁释放
扣减成功,剩余的库存为:5
分布式锁释放
扣减成功,剩余的库存为:3
分布式锁释放
扣减成功,剩余的库存为:1
分布式锁释放
扣减成功,剩余的库存为:0
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放

可以看到,没有超卖现象。至此Redission实现分布式锁已经OK。
redis实现分布式锁 可见博文:【分布式锁】Redis实现分布式锁

相关文章:

【分布式锁】Redission实现分布式锁

接着上一节&#xff0c;我们遇到了超卖的问题&#xff0c;并通过Redis实现分布式锁&#xff0c;进行了解决。本节 我将换一种方式实现分布式锁。 前提&#xff1a; nginx、redis、nacos 模块1&#xff1a; provider-and-consumer 端口 8023 模块2 rabbitmq-consumer 端口 8021 …...

UE4/5 对话系统

参考教程&#xff1a;UE4甜筒教艺术生学蓝图#21.UE4对话系统(1)--唠嗑案例展示_哔哩哔哩_bilibili 说来惭愧两年前看的教程&#xff0c;现在才记录一下&#xff0c;很好的教程推荐大家观看 1.首先创建两个枚举&#xff0c;内容如下 2.创建三个结构体&#xff0c;内容如下 3.再…...

Golang | Leetcode Golang题解之第275题H指数II

题目&#xff1a; 题解&#xff1a; func hIndex(citations []int) int {n : len(citations)return n - sort.Search(n, func(x int) bool { return citations[x] > n-x }) }...

Python—面向过程编程,详细讲解(类和实例,初始化函数,类中封装数据与操作)

1.类和实例 类&#xff1a;类别 实例&#xff08;对象&#xff09;&#xff1a;类型塑造出来的某一个具体的内容 isinstance(对象&#xff0c;类) 返回一个对象是否是一个类的实例 # 声明一个整数类的实例10 a int(10) # a 10 print(type(a), isinstance(a, int)) a flo…...

Linux云计算 |【第一阶段】SERVICES-DAY2

主要内容&#xff1a; DNS服务基础及搭建、特殊解析(针对地址库文件&#xff1a;DNS轮询 DNS泛域名解析 DNS别名&#xff09;、缓存DNS&#xff08;全局转发forwarders&#xff09;、DNS递归迭代&#xff08;子域授权&#xff09;、DNS主从架构搭建、DNS主从数据同步 一、DNS工…...

el-upload照片墙自定义上传多张图片(手动一次性上传多张图片)包含图片回显,删除

需求&#xff1a;el-upload照片墙自定义上传多张图片&#xff08;手动一次性上传多张图片&#xff09;包含图片回显&#xff0c;删除&#xff0c;预览&#xff0c;在网上看了很多&#xff0c;都没有说怎么把数据转为file格式的&#xff0c;找了很久最终实现&#xff0c; 难点&a…...

三星Unpacked发布会即将举行:有新款折叠屏手机,还有智能戒指

随着7月的脚步渐近&#xff0c;科技界的目光再次聚焦于三星&#xff0c;它即将在法国巴黎举办今年的第二场Unpacked发布会。这不仅是一场新品的展示&#xff0c;更是三星对创新科技的一次深刻诠释。 从Galaxy Z Fold 6的全新设计&#xff0c;到Galaxy Z Flip 6的显著升级&…...

【Python】Matplotlib简要教程

文章目录 一、简介二、一些基本概念2.1 图表元素2.2 常见图表类型2.3 主要绘图函数及其返回值2.4 Artists 的概念 三、基本图表详解3.1 成对数据3.11 折线图&#xff1a;plot()&#x1f7e8;设置图表样式&#x1f7e8;设置各种标签&#x1f7e8;设置坐标轴&#x1f7e8;绘制子图…...

数驭未来,景联文科技构建高质大模型数据库

国内应用层面的需求推动AI产业的加速发展。根据IDC数据预测&#xff0c;预计2026年中国人工智能软件及应用市场规模会达到211亿美元。 数据、算法、算力是AI发展的驱动力&#xff0c;其中数据是AI发展的基石&#xff0c;中国的数据规模增长速度预期将领跑全球。 2024年《政府工…...

视频汇聚平台EasyCVR启动出现报错“cannot open shared object file”的原因排查与解决

安防视频监控EasyCVR安防监控视频系统采用先进的网络传输技术&#xff0c;支持高清视频的接入和传输&#xff0c;能够满足大规模、高并发的远程监控需求。EasyCVR平台支持多种视频流的外部分发&#xff0c;如RTMP、RTSP、HTTP-FLV、WebSocket-FLV、HLS、WebRTC、fmp4等&#xf…...

VMware 安装完,设备管理器中没有虚拟网卡(vmnet0、wmnet1、vmnet8) / 虚拟网络编辑器中没有桥接模式

问题&#xff1a;VMware 安装完&#xff0c;设备管理器中没有虚拟网卡(vmnet0、wmnet1、vmnet8) / 虚拟网络编辑器中没有桥接模式 1、确认 Device Install Service 和 Device Setup Manager 没有被禁用 Device Install Service 和 Device Setup Manager是 Windows 操作系统中…...

构建高效Node.js中间层:探索请求合并转发的艺术

&#x1f389; 博客主页&#xff1a;【剑九 六千里-CSDN博客】 &#x1f3a8; 上一篇文章&#xff1a;【CSS盒模型&#xff1a;掌握网页布局的核心】 &#x1f3a0; 系列专栏&#xff1a;【面试题-八股系列】 &#x1f496; 感谢大家点赞&#x1f44d;收藏⭐评论✍ 引言&#x…...

中断和EXIT原理介绍

中断和EXIT原理介绍 一、中断的介绍&#xff1f;二、EXIT的介绍1.EXIT作用2.EXIT的详情3.EXIT中AFIO复用的作用4.STM32中AFIO复用作用 一、中断的介绍&#xff1f; 二、EXIT的介绍 EXTI&#xff08;Extern Interrupt&#xff09;外部中断 1.EXIT作用 EXTI可以监测指定GPIO口…...

vcpkg或者命令行需要设置代理时如何设置

当使用命令行或者vcpkg时&#xff0c;有时候需要设置代理来下载一些代码&#xff0c;那么可以这样&#xff1a; 本地先起一个http或者socks5的代理服务器。监听127.0.0.1:10808如果本地是http代理服务器&#xff0c;在命令行执行&#xff1a; set http_proxyhttp://127.0.0.1:…...

tensorflow安装及数据操作----学习笔记(一)

安装Miniconda 下载对应系统版本的Miniconda。我的系统是ubuntu&#xff0c;所以选择Miniconda3 Linux 64-bit。下载后执行下载的sh脚本 sh Miniconda3-latest-Linux-x86_64.sh -b执行后&#xff0c;运行conda初始化命令 ~/miniconda3/bin/conda init关闭当前命令终端&#…...

顺序表和单链表的经典算法题

目录 前言 一、基础思想&#xff08;数组&#xff09; 1. 移除元素 2.删除有序元素的重复项 3.合并两个有序数组 二、单链表算法 1.移除链表元素 2.翻转链表 3.合并两个有序的链表 前言 Hello,小伙伴们&#xff0c;今天我们来做一个往期知识的回顾&#xff0c;今天我将…...

python基础知识点(蓝桥杯python科目个人复习计划71)

做些简单题 第一题&#xff1a;确定字符串是否包含唯一字符 题目描述&#xff1a; 实现一个算法来识别一个字符串的字符是否是唯一的。 若唯一输出YES&#xff0c;否则输出NO。 输入描述&#xff1a; 输入一个字符串&#xff0c;长度不超过100. 输出描述; 输出一行&…...

【大数据专题】Flink题库

1 . 简述什么是Apache Flink &#xff1f; Apache Flink 是一个开源的基于流的有状态计算框架。它是分布式地执行的&#xff0c;具备低延迟、高吞吐的优秀性能&#xff0c;并且非常擅长处理有状态的复杂计算逻辑场景 2 . 简述Flink 的核心概念 &#xff1f; Flink 的核心概念…...

Python鲁汶意外莱顿复杂图拓扑分解算法

&#x1f3af;要点 &#x1f3af;算法池化和最佳分区搜索&#xff1a;&#x1f58a;网格搜索 | &#x1f58a;发现算法池 | &#x1f58a;返回指定图的最佳划分 | &#x1f58a;返回指定图的最佳分区 | &#x1f3af;适应度和聚类比较功能&#xff1a;&#x1f58a;图的划分 |…...

【C++】类和对象之继承

目录 继承的概念和定义 继承的概念 继承的定义 继承的定义格式 继承关系和访问限定符 继承基类成员访问方式的变化 访问权限实例 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 复杂的菱形继承及菱形虚拟继承 继承的…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...