redis缓存击穿,redisson分布式锁,redis逻辑过期

什么是缓存击穿:

缓存击穿是指在高并发环境下,某个热点数据的缓存过期,导致大量请求同时访问后端存储系统,引起系统性能下降和后端存储压力过大的现象。

解决方案:
1. redisson分布式锁

本质上是缓存重建的过程中,大量的请求访问到后端的数据库导致数据库压力过大
那么可以使用redisson分布式锁来对缓存重建的过程加锁
其它的线程只有缓存重建完毕之后才可以访问
缺点:所有的请求都要等待拿到锁的线程来进行缓存重建
优点:数据拥有高一致性,适用于某些涉及“钱”的业务,或者要求数据的强一致性的。

  1. 新建redisson子工程单独作为微服务名字叫redisson-starter
  2. 引入redisson相关依赖
        <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.17.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.18</version></dependency>
  1. 项目结构
    在这里插入图片描述
    RedissonConfigProperties:一些redisson需要的配置项,如果是集群此处不能用这种方式
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;@Data
@ConfigurationProperties(prefix = "redisson-lock")
public class RedissonConfigProperties {private String redisHost;private String redisPort;}

RedissonConfig:配置RedissonClient,并且加入了一些自动装配的配置

import com.yonchao.redisson.service.RedissonLockService;
import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.io.IOException;@Data
@Configuration
@EnableConfigurationProperties({RedissonConfigProperties.class})
//当引入Service接口时
@ConditionalOnClass(RedissonLockService.class)
public class RedissonConfig {@Autowiredprivate RedissonConfigProperties redissonConfigProperties;/*** 对 Redisson 的使用都是通过 RedissonClient 对象* @return*/@Bean(destroyMethod="shutdown") // 服务停止后调用 shutdown 方法。public RedissonClient redisson() {// 1.创建配置Config config = new Config();// 集群模式// config.useClusterServers().addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001");// 2.根据 Config 创建出 RedissonClient 示例。config.useSingleServer().setAddress("redis://"+redissonConfigProperties.getRedisHost()+":"+redissonConfigProperties.getRedisPort());return Redisson.create(config);}
}

spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.yonchao.redisson.service.RedissonLockService

业务类:

import com.yonchao.redisson.service.RedissonLockService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Service
public class RedissonLockServiceImpl implements RedissonLockService {@Autowiredprivate RedissonClient redissonClient;/*** 加锁* @param lockKey* @return*/public boolean acquireLock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);try {return lock.tryLock(30, TimeUnit.SECONDS);} catch (InterruptedException e) {Thread.currentThread().interrupt();return false;}}/*** 释放锁* @param lockKey* @return*/public void releaseLock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);lock.unlock();}
}
  1. 其它微服务通过pom引入redisson-starter微服务
    在这里插入图片描述
  2. 重建缓存过程中使用分布式锁
    首先注入RedissonClient
    接着判断布隆过滤器
    接着从缓存中读数据
    读不到的话需要重建缓存
    重建缓存:
    首先获取分布式锁
    获取成功了就查询数据库并且重建缓存返回数据最后释放锁
    获取分布式锁失败就等待1秒接着递归这个方法,直到有一个线程重建缓存成功。
    /*** 使用逻辑过期的方式* @param id* @return*/@Overridepublic ResponseResult selectArticleLogicalExpiration(Long id) {// 首先经过布隆过滤器// 判断这个id是不是在布隆过滤器中boolean mightContain = bloomFilter.mightContain(id);// 不存在直接返回if (!mightContain) {return ResponseResult.okResult();}// 首先从缓存中获取数据Object articleObj = redisTemplate.opsForValue().get(ARTICLE_KEY + id);if (Objects.nonNull(articleObj)){String articleJSON = (String) articleObj;JSONObject jsonObject = JSON.parseObject(articleJSON);Long expired = jsonObject.getLong("expired");// 旧的文章对象ApArticle article = JSON.parseObject(articleJSON, ApArticle.class);if (Objects.nonNull(expired)){// 未过期直接返回if (expired - System.currentTimeMillis() > 0) {return ResponseResult.okResult(article);}// 过期了进行缓存的重建boolean acquiredLock = redissonLockService.acquireLock(lockKeyRedisson);// 拿到锁了就 新开一个线程 进行缓存的重建 此处使用分布式锁,只会有一个线程抢占到缓存重建所以不用使用线程池if (acquiredLock) {try {new Thread(() -> {// 直接重建缓存,不关心返回值rebuildCache(id);}).start();} finally {// 最后释放锁redissonLockService.releaseLock(lockKeyRedisson);}}// 开启多线程后直接返回旧的数据return ResponseResult.okResult(article);}}// 缓存中根本没有,那么需要直接加锁重建缓存,此时不能多线程的去重建缓存,只能通过分布式锁的方式,boolean lockAcquired = redissonLockService.acquireLock(lockKeyLogicalExpiration);if (lockAcquired){try {ApArticle apArticle = rebuildCache(id);if (Objects.isNull(apArticle)){// 数据不存在就直接返回return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);}// 返回获得的文章数据return ResponseResult.okResult(apArticle);} finally {// 最后释放锁redissonLockService.releaseLock(lockKeyLogicalExpiration);}} else {// 没有获取到锁就等待一段时间然后再次尝试获取锁try {Thread.sleep(1000);}catch (Exception e){log.error(e.getMessage());}// 等待一段时间重新校验有没有缓存return selectArticleLogicalExpiration(id);}}public ApArticle rebuildCache(Long id){// 重建缓存ApArticle articleDatabase = getById(id);// 重建缓存if (Objects.nonNull(articleDatabase)) {// 设置逻辑过期时间// 转为jsonStringString articleJsonString = JSON.toJSONString(articleDatabase);// 转为JSONObjectJSONObject articleJsonObject = JSON.parseObject(articleJsonString);// 当前时间戳加上 设置的过期时间*1000 因为时间戳是毫秒articleJsonObject.put("expired", System.currentTimeMillis() + ARTICLE_EXPIRED * 1000);redisTemplate.opsForValue().set(ARTICLE_KEY + id, JSON.toJSONString(articleJsonObject));// 布隆过滤器过滤过的,这个肯定存在return articleDatabase;}return null;}

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

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

相关文章

「Verilog学习笔记」四选一多路器

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 通过波形示意图我们可以发现&#xff0c;当sel为0&#xff0c;1&#xff0c;2时&#xff0c;输出mux_out分别为d3&#xff0c;d2&#xff0c;d1&#xff0c;那么sel3…

PHP中文转拼音实现

pinyin.php 床前明月光&#xff0c;疑是地上霜。 举头望明月&#xff0c;低头思故乡 <?php /*** PHP 汉字转拼音 [包含20902个基本汉字5059生僻字]* author 楼教主(cik520qq.com)* version v1.2* note 请开启 mb_string 扩展*/var_dump(pinyin(床前明月光&#xff0c;疑是…

【Redis】的简介和安装配置(Linux和windows)及操作命令

目录 一、概述 1.介绍 2.特点 二、安配 1. 安装 2. 配置 3. 主机连接 1.Linux连接 2.windows连接 三、命令 1. 字符串(String) 2. 哈希(Hash) 3. 列表&#xff08;List&#xff09; 4. 集合&#xff08;Set&#xff09; 一、概述 1.介绍 Redis是一个开源的、基…

零代码复现-TCGA联合GEO免疫基因结合代谢基因生信套路(二)

零代码复现-TCGA联合GEO免疫基因结合代谢基因生信套路&#xff08;二&#xff09;-关键基因集的获取和生存数据准备 前面的分析中&#xff0c;下载TCGA和GEO的数据&#xff0c;并进行简单的处理&#xff0c;接下来就是相关基因集的获取和整理&#xff0c;为后期聚类和降维做准…

【PyQt学习篇 · ⑥】:QWidget - 事件

文章目录 事件消息显示和关闭事件移动事件调整大小事件鼠标事件进入和离开事件鼠标按下和释放事件鼠标双击事件鼠标按下移动事件 键盘事件焦点事件拖拽事件绘制事件改变事件右键菜单输入法 事件转发机制案例一案例二案例三 事件消息 显示和关闭事件 showEvent(QShowEvent)方法…

小白如何制作电子画册?看这里,超多画册模板任你挑!

传统纸质版的画册&#xff0c;制作起来即费力又费时&#xff0c;花费还高&#xff0c;想要修改内容还得重新制作&#xff0c;特别麻烦。现在互联网发达&#xff0c;如今已经用上了H5的技术&#xff0c;小白也能快速制作一本翻页电子画册。 只需用FLBOOK&#xff0c;在线就可以制…

Linux的历史与环境

目录 Linux的背景介绍 Linux的时代背景-硅谷模式 计算机发展 UNIX发展历史 Linux诞生的偶然与必然 Linux开源 Linux发行版本 搭建Linux的环境 1.直接安装在物理机上 2.使用虚拟机软件 3.使用云服务器 &#xff08;1&#xff09;购买云服务器 &#xff08;2&#x…

OceanBase:03-集群部署

目录 一、集群规划 二、配置要求 三、部署前配置 1.配置 limits.conf 2.配置 sysctl.conf 3.关闭防火墙 4.关闭 SELinux 5.创建数据目录&#xff0c;修改文件所有者信息 6.设置无密码 SSH 登录 7.安装jdk 四、解压执行安装 五、集群部署 1.OBD命令行部署 2. OBD白…

2019年408真题复盘

紫色标记是认为有一定的思维难度或重点总结 红色标记是这次刷真题做错的 记录自己对题目的一些想法与联系&#xff0c;可能并不太关注题目本身。 分数用时 选择部分 80/8036min大题部分41/7094min总分121130min 摘自知乎老哥&#xff1a;“我做历年真题时&#xff0c;绝大部分…

图数据库Neo4j——SpringBoot使用Neo4j 简单增删改查 复杂查询初步

前言 图形数据库是专门用于存储图形数据的数据库&#xff0c;它使用图形模型来存储数据&#xff0c;并且支持复杂的图形查询。常见的图形数据库有Neo4j、OrientDB等。 Neo4j是用Java实现的开源NoSQL图数据库&#xff0c;本篇博客介绍如何在SpringBoot中使用Neo4j图数据库&…

python连接clickhouse (CK)

Author: tkhywang 2810248865qq.com Date: 2023-11-01 11:28:58 LastEditors: tkhywang 2810248865qq.com LastEditTime: 2023-11-01 11:36:25 FilePath: \PythonProject02\Python读取clickhouse2 数据库数据.py Description: 这是默认设置,请设置customMade, 打开koroFileHead…

【Linux】:Linux开发工具之Linux编辑器vim的使用

&#x1f52b;1.Linux编辑器-vim使用 &#x1f4e4; vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以…

FPGA_Signal TapII 逻辑分析仪 在线信号波形抓取

FPGA_Signal TapII 逻辑分析仪 在线信号波形抓取 由于一些工程的仿真文件不易产生&#xff0c;所以我们可以利用 quartus 软件自带的 SignalTap 工具对波形进行抓取 对各个信号进行分析处理&#xff0c;让电子器件与FPGA进行正常通讯工作&#xff0c;也验证所绘制的波形图是否一…

【C++】类和对象(中)之拷贝构造与运算符、操作符重载

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 我们继续学习默认成员函数&#xff0c;本篇文…

③ 软件工程CMM、CMMI模型【软考中级-软件设计师 考点】

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ ③ 软件工程CMM、CMMI模型【软考中级-软件设计…

Android 数据恢复的顶级软件分享

人们经常向我们询问有关 Android 数据恢复软件的信息以及它们是否有用。而且&#xff0c;我们给他们讲了两个朋友的故事——凯伦和亚历克斯。他们都丢失了 Android 手机上的一些重要数据。 丢失数据确实是一个令人心碎的时刻&#xff0c;根据丢失的文件&#xff0c;可能会让您…

橙河网络:坏人是怎么形成的?

小A是一个非常热心的人&#xff0c;给谁帮忙&#xff0c;都免费。 大家都说&#xff0c;小 A&#xff0c;实在人呀&#xff0c;哈哈。 小B搬来了&#xff0c;他活多&#xff0c;弄不过来&#xff0c;常找小 A 来帮忙。 小A 每次来帮忙&#xff0c;小B 都给小A一张大团结(100…

oracle (8)Managing Tablespace Data File

目录 一、基础知识 1、表空间和数据文件 2、存储层次结构摘要 3、表空间的类型 4、表空间中的空间管理 5、临时表空间 6、Default Temporary TS 默认临时TS 二、常用实操 1、Creating Tablespaces创建表空间 2、Dictionary-Managed TS 字典管理的表空间 3、Locally …

【idea】生成banner.txt

Spring Boot banner在线生成工具&#xff0c;制作下载英文banner.txt&#xff0c;修改替换banner.txt文字实现自定义&#xff0c;个性化启动banner-bootschool.netSpring Boot banner工具实现在线生成banner&#xff0c;轻松修改替换实现自定义banner&#xff0c;让banner.txt文…

pix2tex - LaTeX OCR 安装使用记录

系列文章目录 文章目录 系列文章目录前言一、安装二、使用三、如果觉得内容不错&#xff0c;请点赞、收藏、关注 前言 项目地址&#xff1a;这儿 一、安装 版本要求 Python: 3.7 PyTorch: >1.7.1 安装&#xff1a;pip install "pix2tex[gui]" 注意&#xff1a…