2、基于redis实现分布式锁
目录
- 2.1. 基本实现
- ==2.2. 防死锁==
- ==2.3. 防误删==
- 2.4. redis中的lua脚本
- 2.4.1 redis 并不能保证
- 2.4.2 lua介绍
- 2.5. 使用lua保证删除原子性
2.1. 基本实现
借助于redis中的命令setnx(key, value),key不存在就新增,存在就什么都不做。同时有多个客户端发送setnx命令,只有一个客户端可以成功,返回1(true);其他的客户端返回0(false)。
- 多个客户端同时获取锁(setnx)
- 获取成功,执行业务逻辑,执行完成释放锁(del)
- 其他客户端等待重试
改造StockService方法:
/*** redis setnx实现分布式锁,最基本的哪一种 !!!*/public void deduct() {// 加锁setnxBoolean lock = this.redisTemplate.opsForValue().setIfAbsent("lock", "111");if (!lock) {// 没有获取到锁,进行重试!!try {Thread.sleep(50);this.deduct();} catch (InterruptedException e) {e.printStackTrace();}} else {try {// 1. 查询库存信息String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");// 2. 判断库存是否充足if (stockStr != null && stockStr.length() != 0) {Long stock = Long.parseLong(stockStr);if (stock > 0) {redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));}}} finally {// 解锁this.redisTemplate.delete("lock");}}}
使用 jmeter 进行压测
查看库存数量
上述代码优化,不断重试的过程中一直进行递归,最终导致栈的溢出。
解决
/*** while循环代替递归,解决不断重试可能导致的栈溢出的问题*/public void deduct() {// 加锁setnxwhile (this.redisTemplate.opsForValue().setIfAbsent("lock1", "1")) {try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}try {// 1. 查询库存信息String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");// 2. 判断库存是否充足if (stockStr != null && stockStr.length() != 0) {Long stock = Long.parseLong(stockStr);if (stock > 0) {redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));}}} finally {// 解锁this.redisTemplate.delete("lock1");}}}
2.2. 防死锁
问题:setnx刚刚获取到锁,当前服务器宕机,导致del释放锁无法执行,进而导致锁无法锁无法释放(死锁)
解决:给锁设置过期时间,自动释放锁。
设置过期时间两种方式:
- 通过expire设置过期时间(缺乏原子性:如果在setnx和expire之间出现异常,锁也无法释放)
- 使用set指令设置过期时间:set key value ex 3 nx(既达到setnx的效果,又设置了过期时间)
2.3. 防误删
持有锁的线程在锁的内部出现了阻塞,导致他的锁自动释放,这时其他线程,线程2来尝试获得锁,就拿到了这把锁,然后线程2在持有锁执行过程中,线程1反应过来,继续执行,而线程1执行过程中,走到了删除锁逻辑,此时就会把本应该属于线程2的锁进行删除,这就是误删别人锁的情况说明
解决: setnx获取锁时,设置一个指定的唯一值(例如:uuid);释放前获取这个值,判断是否自己的锁
问题:删除操作缺乏原子性。
场景:
- index1执行删除时,查询到的lock值确实和uuid相等
- index1执行删除前,lock刚好过期时间已到,被redis自动释放
- index2获取了lock
- index1执行删除,此时会把index2的lock删除
解决方案:没有一个命令可以同时做到判断 + 删除,所有只能通过其他方式实现(LUA脚本)
2.4. redis中的lua脚本
2.4.1 redis 并不能保证
redis采用单线程架构,可以保证单个命令的原子性,但是无法保证一组命令在高并发场景下的原子性。
如果redis客户端通过lua脚本把3个命令一次性发送给redis服务器,那么这三个指令就不会被其他客户端指令打断。Redis 也保证脚本会以原子性的方式执行: 当某个脚本正在运行的时候,不会有其他脚本或 Redis 命令被执行。 这和使用 MULTI/ EXEC 包围的事务很类似。
2.4.2 lua介绍
2.5. 使用lua保证删除原子性
相关文章:

2、基于redis实现分布式锁
目录 2.1. 基本实现2.2. 防死锁2.3. 防误删2.4. redis中的lua脚本2.4.1 redis 并不能保证2.4.2 lua介绍 2.5. 使用lua保证删除原子性 2.1. 基本实现 借助于redis中的命令setnx(key, value),key不存在就新增,存在就什么都不做。同时有多个客户端发送setn…...

【问题记录】Ubuntu 22.04 环境下,程序报:段错误(核心已转储)怎么使用 core 文件和GDB调试器 解决?
目录 环境 问题情况 解决思路 原因分析 解决方法 番外知识 环境 VMware Workstation 16 Pro (版本:16.1.2 build-17966106)ubuntu-22.04.2-desktop-amd64 问题情况 本人在运行百万并发的服务端程序时,程序运行报:…...
9 Linux实操篇-实用指令
9 Linux实操篇-实用指令 文章目录 9 Linux实操篇-实用指令9.1 指定和修改运行级别-init/systemctl9.2 找回root密码9.3 Linux的指令说明9.3 帮助类-man/help9.4 文件目录类-pwd/ls/cd/mkdir/...9.5 时间日期类-date/cal9.6 搜索查找类-find/locate/which/grep9.7 压缩和解压类-…...

Hbase基础概念
HBase 一、HBase的数据模型1.HBase数据存储结构2.HBase存储概念3.HBase基本架构 二、HBase Shell1.DDL(Data Definition Language)1.namespace2.table 2.DML(Data Manipulation Language)1.写入数据2.读取数据3.删除数据 三、HBase组成架构1. Master架构…...
JTS-Angle角度类
目录: 获取AB连线与正北方向的角度求距离此点一定距离、一定夹角的点经纬度判断point点 在线段startPoint-etartPoint的左侧或者右侧米转换为弧度弧度转换为米 定义Point点 public class LatLngPoint {final static double RC 6378137;final static double RJ …...

pytest---环境切换(base-url)
前言 前面小编介绍了如何通过pytest的插件来实现自动化测试的环境的切换,当时使用的方法是通过钩子函数进行获取命令行参数值,然后通过提前配置好的参数进行切换测试环境地址,今天小编再次介绍一种方法,通过pytest的插件ÿ…...

linux跑代码,程序终止了,但资源没有释放。
linux跑代码,程序终止了,但资源没有释放。 程序终止,但是资源没有释放. kill -9 5062完成。 linux终止进程...

数据结构--线性表2-1
目录 一、线性结构的定义 二、线性表的表示 三、顺序表的实现(或操作) 1、修改: 2、插入: 四、顺序表的运算效率分析:时间效率分析: 一、线性结构的定义 若结构时非空有限集,则有且仅有一个…...

网访问内网机器:基于frp的内网穿透
随缘更新些我自己的博客网站里的文章吧 因为经常需要远程访问自己的机器,所以写一个博客记录一下 公网访问内网机器:基于frp的内网穿透 从公网中访问自己的私有设备向来是一件难事儿。 1. 为什么需要内网穿透? A. 计算机网络 如何在自己的机…...

【Spring框架】Spring读取与存储综合练习
练习 在 Spring 项⽬中,通过 main ⽅法获取到 Controller 类,调⽤ Controller ⾥⾯通过注⼊的⽅式调⽤ Service 类,Service 再通过注⼊的⽅式获取到 Repository 类,Repository 类⾥⾯有⼀个⽅法构建⼀个 User 对象,返…...

Python实现指定区域桌面变化监控并报警
在这篇博客中,我们将使用Python编程语言和一些常用的库来实现一个简单的区域监控和变化报警系统。我们将使用Tkinter库创建一个图形界面,允许用户选择监控区域,并使用OpenCV库进行图像处理和相似性比较,以检测区域内的变化&#x…...

【数据结构】实验五:栈
实验五 栈 一、实验目的与要求 1)熟悉栈的类型定义和基本操作; 2)灵活应用栈解决具体应用问题。 二、实验内容 1、判断回文数,回文是指正读反读均相同的字符序列,如“1221”和“12321”均是回文,但“…...

⚡️⚡️Java多线程编程的高效、安全实践
⚡️ Java多线程编程的高效、安全实践⚡️ ☀️ 1 摘要☀️2 多线程编程基础☀️ 3 线程同步与互斥☀️ 4 并发集合类与原子操作☀️ 5 线程池与执行器框架☀️ 6 并发编程的最佳实践🌄 7 总结 博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客…...

【云原生】Docker私有仓库registry
目录 1)用docker容器运行registry私有仓库服务。 2)运行私有仓库服务 3)镜像重命名(要上传的镜像名需要注明私仓的ip) 4)编辑docker配置文件(因为默认是拉取docker官方的镜像,需要重新指定) 5)其他dock…...

第十四届蓝桥杯大赛青少年省赛C++组试题真题 2023年5月
一、选择题 第 1 题 单选题 C中,bool类型的变量占用字节数为 ( )。 A. 1 B. 2 C. 3 D. 4 第 2 题 单选题 以下关于C结构体的说法,正确的是 ( )。 A. 结构体中只能包含成员变量,不能包含成员函数 B. 结构体不能从另一个结构体继承 …...

GAN论文精读
标题:Generative Adversarial Nets 摘要: 简写:作者提出了一个framework通过一个对抗的过程,在这里面会同时训练两个模型。 第一个模型为生成模型G,是用来抓住整个数据的分布 第二个模型为辨别模型D,是用来估计一个样本是否从G中产生。 …...
数据结构:计数排序(详解)
思路详解: 1 找到数组中的最大值、最小值 2 开辟一个统计每个数据出现次数的数组(总个数是最大值-最小值1,因为下标范围是0~最大值-最小值,闭区间统计个数要1) 3 遇到一个元素,在此元素-最小值作为下标的…...

1 请使用js、css、html技术实现以下页面,表格内容根据查询条件动态变化。
1.1 创建css文件,用于编辑style 注意: 1.背景颜色用ppt的取色器来获取: 先点击ppt的形状轮廓,然后点击取色器,吸颜色,然后再点击形状轮廓的其他轮廓颜色,即可获取到对应颜色。 2.表格间的灰色线…...

react-native项目安卓版本升级 compileSdkVersion 29->31
因为 react-native-ble-manager添加过程及碰到的问题 依赖 https://github.com/innoveit/react-native-ble-manager 参考:https://blog.csdn.net/withings/article/details/71378562 iOS 按react-native-ble-manager 文档在 【Info.plist】加了key之后能正常使用…...

【学习笔记】目标跟踪领域SOTA方法比较
目录 前言方法1 TraDeS:2 FairMOT:3 SMILEtrack:4 ByteTrack: 前言 常用于行人跟踪的多目标跟踪数据集包括:MOT 15/16/17/20、PersonPath22等… 为更好比较现有SOTA算法的检测性能,本博客将针对在各数据集上表现较优的算法模型进行介绍。(表…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...

Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”
案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...