在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的张力…...

【Vue】模板语法,事件处理器及综合案例、自定义组件、组件通信
一、事件处理器 我们之前事件监听可以使用v-on 指令 1、事件修饰符 在Vue中我们通过由点(.)表示的指令后缀来调用修饰符,比如: .stop:阻止事件冒泡。当事件触发时,该修饰符将停止事件进一步冒泡到父元素。相当于调用了 event.stop…...

从0开始写中国象棋-创建棋盘与棋子
从控制台版本开始 考虑到象棋程序,其实就是数据结构与算法实现。 所以和界面相关的QT部分我们先放一放。 我们从控制台版本开始。这样大家更容易接受,也不影响开发。 后面我们会把控制台嫁接到QT上完成完整的游戏,那时候自然就水到渠成了…...

软件的开发步骤,需求分析,开发环境搭建,接口文档 ---苍穹外卖1
目录 项目总览 开发准备 开发步骤 角色分工 软件环境 项目介绍 产品原型 技术选型 开发环境搭建 前端:默认已有 后端 使用Git版本控制 数据库环境搭建 前后端联调 登录功能完善 导入接口文档 使用swagger 和yapi的区别 常用注解 项目总览 开发准备 开发步骤…...

Qt扫盲-QSqlQueryModel理论总结
QSqlQueryModel理论总结 一、概述二、使用1. 与 view 视图 绑定2. 分离视图,只存数据 一、概述 QSqlQueryModel是用于执行SQL语句和遍历结果集的高级接口。它构建在较低级的 QSqlQuery之上,可用于向QTableView 等视图类提供数据,也是使用了Q…...

分类预测 | MATLAB实现WOA-CNN-BiGRU-Attention数据分类预测(SE注意力机制)
分类预测 | MATLAB实现WOA-CNN-BiGRU-Attention数据分类预测(SE注意力机制) 目录 分类预测 | MATLAB实现WOA-CNN-BiGRU-Attention数据分类预测(SE注意力机制)分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MATLA…...

【单调栈】496. 下一个更大元素 I
496. 下一个更大元素 I 解题思路 首先计算nums2的每一个元素的下一个比他大的元素,使用单调栈将上面的结果和nums2中的每一个元素组成映射map针对每一个Nums1的元素 查询map 记录map 的value class Solution {public int[] nextGreaterElement(int[] nums1, int[…...

搭建Vue的开发环境,Edge浏览器安装VUE拓展工具
一、在下载vue.js文件 在vue官网中下载开发版本的vue.js文件--> 安装 — Vue.js (vuejs.org) 二、将vue.js导入到项目中 这时候我们运行项目控制台会抛出两个错误 三、安装拓展工具 这里以Edge浏览器为例,其他浏览器上可在拓展管理商店中下载 进入Edge的拓展…...

14:00面试,14:06就出来了,这问的谁顶得住啊
从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到8月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%,…...

python 探索分形世界|曼德布洛特|np.frompyfunc()
文章目录 分形的重要特征曼德布洛特集合曼德布洛特集合有一个以证明的结论:图像展示np.ogrid[]np.frompyfunc()集合转图像 julia集合 无边的奇迹源自简单规则的无限重复 ---- 分形之父Benoit B.Mandelbrot 分形的重要特征 自相似性无标度性非线性 曼德布洛特集合…...

Android MVVM示例项目
项目地址 GitHub - yaolunwei/Androidbbc at androidx 项目简介 BBC(基础业务组件) 业务组件的基础,所有业务组件必须基于该组件进行开发,提供一站式开发 快速使用 gradle: implementation com.bigoat.android:bbc:0.0.1 约定成俗 以下继承关系…...