在SpringBoot中利用Redis实现互斥锁
在SpringBoot中利用Redis实现互斥锁
基本知识
前提条件,有一个能够在Springboot中使用Redis的项目,或者能够直接开也行
为什么要实现互斥锁:当我们利用Redis存储热点数据时,突然就过期失效或者被删除了,导致大量请求同时访问数据库,增加了数据库的负载。为减轻数据库的负载我们利用互斥锁。
业务的一个逻辑图流程:

核心思路:相较于原来从缓存中查询不到数据后直接查询数据库而言,现在的方案是 进行查询之后,如果从缓存没有查询到数据,则进行互斥锁的获取,获取互斥锁后,判断是否获得到了锁,如果没有获得到,则休眠,过一会再进行尝试,直到获取到锁为止(这个尝试,要重新从Redis再次尝试获取数据,可能别的锁已经获取到了),才能进行查询
如果获取到了锁的线程,再去进行查询,查询后将数据写入redis,再释放锁,返回数据,利用互斥锁就能保证只有一个线程去执行操作数据库的逻辑,防止缓存击穿
操作锁的核心思路就是利用redis的setnx方法来表示获取锁,该方法含义是redis中如果没有这个key,则插入成功,返回1
具体实现
- 设置锁,删除锁
/*** 根据name对特定的数据进行锁* @param name* @return*/
public boolean setLock(String name) {return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(name, true, 10, TimeUnit.SECONDS));
}public boolean releaseLock(String name) {return Boolean.TRUE.equals(redisTemplate.delete(name));
}
- 具体流程实现
@GetMapping("/getOneByLock/{sequence}")
public BaseResponse<Sentences> getOneByLock(@PathVariable long sequence) {// 从redis中查信息String name = "test:redis:sentences:"+ sequence;Sentences sentence = (Sentences) redisTemplate.opsForValue().get(name);// 命中返回数据if(sentence != null ){redisTemplate.expire(name,2,TimeUnit.MINUTES);return ResultUtils.success(sentence);}// 未命中获取锁String LOCK_NAME = "test:redis:lock:" + sequence;boolean lock = redisTemplate.opsForValue().get(LOCK_NAME) != null && (boolean) redisTemplate.opsForValue().get(LOCK_NAME);//如果lock等于false 那么就可以获取到锁并且,锁住不许其他人操作if(!lock){return ResultUtils.success(setLockReleaseLockAboutSentence(LOCK_NAME,name,sequence));}// 没有获取到锁 休眠一段时间,并且反复检测redis中的数据是否存在,或者锁是否释放while(true){try {Thread.sleep(1000);log.error("等待中");} catch (InterruptedException e) {throw new RuntimeException(e);}// 检查是否存在值sentence = (Sentences) redisTemplate.opsForValue().get(name);if(sentence != null){return ResultUtils.success(sentence);}boolean checkAgain = (boolean) redisTemplate.opsForValue().get(LOCK_NAME);if(!checkAgain){sentence = setLockReleaseLockAboutSentence(LOCK_NAME,name,sequence);}return ResultUtils.success(sentence);}
}public Sentences setLockReleaseLockAboutSentence(String LOCK_NAME,String redisName, long sequence){// 设置 锁值 为truesetLock(LOCK_NAME);// 并且从数据中查取数据Sentences sentence = sentencesService.getById(sequence);// 这里为了明显不能抢锁设置一个睡眠时间try {log.error("休眠中");Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}
// 把数据写入RedisredisTemplate.opsForValue().set(redisName,sentence,2, TimeUnit.MINUTES);// 释放锁releaseLock(LOCK_NAME);// 返回数据return sentence;
}
代码说明,在这个代码中为了演示明显,获取锁中延迟3s,竞争锁会延迟1s,下面的演示,初始时Redis中没有数据,只能去数据库中取数据,但是设置了互斥锁,所以只能够一个线程进入数据库取数据,其他只能等待数据得到结果。
结果示意
- redis中无数据

- 结果

最终效果是好的。redis中已存入数据

相关文章:
在SpringBoot中利用Redis实现互斥锁
在SpringBoot中利用Redis实现互斥锁 基本知识 前提条件,有一个能够在Springboot中使用Redis的项目,或者能够直接开也行 为什么要实现互斥锁:当我们利用Redis存储热点数据时,突然就过期失效或者被删除了,导致大量请求同…...
vue3+eleement plus日历选择季度
<template><div class"el-quarter-wrap"><el-popover width"280" v-model"visible"><template #reference><el-input v-model"quarterDate" placeholder"请选择季度" clearable :prefix-icon&qu…...
实现动态业务规则的方法(Java)
实现动态业务规则的方法(Java) 企业信息化系统核心在于业务领域的概念模型及于此基础上复杂多变的业务规则,实现中通常抽象规则的接口方法,使用继承或策略等设计模式实现不同的业务规则的实现。领域的概念模型在特定领域是稳定的…...
leetcodeTOP100(26)两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 …...
performance_schema
插桩名称的最左边部分表示插桩类型,其余部分从左到右依次表示到特定的子系统 mysql> select * from performance_schema.setup_instruments where documentation is not null limit 5,5\G; *************************** 1. row ***************************NAME:…...
全新UI基于Thinkphp的最新自助打印系统/云打印小程序源码/附教程
这是一款全新的基于Thinkphp的最新自助打印系统,最新UI界面设计的云打印小程序源码,带有简单的教程。 下载地址:https://bbs.csdn.net/topics/617324130...
Android 13.0 framework层系统手势增加上滑手势home事件功能(相当于Home键)
1.概述 在13.0的定制化开发系统手势功能的时候,客户需求要求在上滑手势的时候,在底部上滑时候进入系统桌面,也就是增加 home键功能,所以就需要分析相关的系统手势上滑事件,然后添加home事件这样 就可以实现这个功能了 2.framework层系统手势增加上滑手势home事件功能的核…...
webp格式及其转成
"WebP" 是一种现代的图像压缩格式,由谷歌公司开发。它旨在提供高质量的图像压缩,同时减小图像文件的大小,从而加快网络加载速度。WebP 格式通常使用 ".webp" 扩展名来标识。 WebP 图像格式主要有以下几个特点和优点&…...
echo cat find grep命令
目录 cat echo grep find cat cat命令可以理解为英文单词concatenate的缩写,其功能是连接多个文件并且打印到屏幕输出,或者重定向到指定文件中。此命令常用于显示单个文件内容,或者将几个文件内容连接起来一起显示,还可以从标…...
Linux学习第20天:Linux按键输入驱动开发: 大道至简 量入为出
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 中国文化博大精深,太极八卦,阴阳交合,变化无穷。在程序的开发中也是这样,数字0和1也是同样的道理。就本节来说&am…...
WordPress主题开发( 七)之—— 模版文件继承规则
WordPress主题开发( 七)之—— 模版文件继承规则 概述模板文件层次结构示例可视化概述层次结构详细信息主页显示首页显示单文章页面单页分类目录标签自定义分类自定义文章类型作者显示日期搜索结果404(未找到)附件嵌入功能非ASCII…...
Simulink 封装
快捷键: Edit Mask:CtrlM Look Under Mask:CtrlU 封装之后的模型: Edit Mask界面: 双击模块后的提示界面: 封装的模块内部:...
【AI视野·今日Robot 机器人论文速览 第三十六期】Tue, 19 Sep 2023
AI视野今日CS.Robotics 机器人学论文速览 Tue, 19 Sep 2023 (showing first 100 of 112 entries) Totally 112 papers 👉上期速览✈更多精彩请移步主页 Interesting: 📚In-Hand Object Rotation, RotateIt 提出了一种基于视觉与触觉的物体旋转朝向的方法…...
Java随笔
动态SQL 是指根据不同的条件或参数生成不同的SQL语句的技术。在实际开发中,我们经常需要根据用户的输入或其他条件来生成不同的SQL语句,动态SQL就能满足这个需求。 在Java中,使用MyBatis作为ORM框架时,可以通过在Mapper.xml文件…...
ARINC825规范简介
ARINC825规范简介 机载CAN网络通用标准 ARINC825规范全称为机载CAN网络通用标准(The General Standardization of CAN for Airborne Use)。顾名思义,ARINC825规范是建立在CAN物理网络基础上的高层规范。CAN网络使用共享的双绞电缆传输数据&…...
SQLAlchemy列参数的使用和query函数的使用
目录 Column常用参数 代码演示 代码刨析 query函数的使用 基本用法 常见用法示例 查询所有记录 根据条件查询 查询第一条符合条件的记录 查询特定列的值 添加排序规则 使用聚合函数 连接查询 使用filter_by Column常用参数 primary_key:True设置某个字…...
产权未转移登记的离婚析产协议不能对抗债权人
债权人代位析产纠纷作为一个新的民事案由,是民事执行阶段中债务人不能到期清偿债务,又怠于分割共同财产或以诉讼方式分割共同财产,而由债权人请求代替债务人向其他共有人提出分割财产以实现债权的诉讼。债权人代位析产,增加了债权…...
python+nodejs+php+springboot+vue 导师双选系统
为了直观显示系统的功能,运用用例图这样的工具显示分析的结果。分析的导师功能如下。导师管理导师选择信息,管理项目,管理项目提交并对学员提交的项目进行指导。 为了直观显示系统的功能,运用用例图这样的工具显示分析的结果。分析…...
paddle2.3-基于联邦学习实现FedAVg算法
目录 1. 联邦学习介绍 2. 实验流程 3. 数据加载 4. 模型构建 5. 数据采样函数 6. 模型训练 1. 联邦学习介绍 联邦学习是一种分布式机器学习方法,中心节点为server(服务器),各分支节点为本地的client(设备&#…...
伺服丝杠系统常用运算功能块
这篇博客主要介绍伺服、丝杠系统常用的运算功能块,其它相关运算可以查看下面文章链接: 信捷PLC脉冲频率、位移、转速相关计算(C语言编程应用)_RXXW_Dor的博客-CSDN博客里工业控制张力控制无处不在,也衍生出很多张力控制专用控制器,磁粉制动器等,本篇博客主要讨论PLC的张力…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
