SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁

文章目录

    • 1、步骤
    • 2、具体过程
      • 1、引入pom依赖
      • 2、修改配置文件
      • 3、单元测试
      • 4、测试结果
    • 3、redis运行情况
    • 4、项目中实际应用
    • 5、加锁解决缓存击穿问题
      • 代码一(存在问题)
      • 代码二(问题解决)
    • 6、新问题
    • 7、分布式锁

三连哦

1、步骤

前提条件:已经安装了Redis

  • 1、pom中引入依赖
  • 2、配置文件中配置
  • 3、项目中使用

2、具体过程

1、引入pom依赖

版本由父工程管理

        <!--引入redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

在这里插入图片描述

2、修改配置文件

spring:
  redis:
    host: 192.168.202.211
    port: 6379

在这里插入图片描述

3、单元测试

这里有关stringRedisTemplate的使用、请自行查阅

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Test
    public void testRedis(){
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        //保存
        ops.set("hello", UUID.randomUUID().toString());
        //查询
        String hello = ops.get("hello");
        System.out.println("之前保存的数据是:"+hello);
        
    }

4、测试结果

在这里插入图片描述

3、redis运行情况

我这里用docker安装redis、查看容器运行情况

在这里插入图片描述

4、项目中实际应用

代码逻辑
在这里插入图片描述

测试

访问接口数据
在这里插入图片描述

redis可视化工具查看

在这里插入图片描述

5、加锁解决缓存击穿问题

代码一(存在问题)

    @Override
    @Cacheable(value = {"category"},key = "#root.methodName",sync = true)
    public Map<String, List<Catalog2Vo>> getCatalogJsonDbWithSpringCache() {
        //1、缓存中放入json字符串,拿出json字符串,需要逆转为能用的对象类型【序列化和反序列化】
        String catalogJSON = stringRedisTemplate.opsForValue().get("catalogJSON");
        if(StringUtils.isEmpty(catalogJSON)){
            //2、缓存中没有,查询数据库
            Map<String, List<Catalog2Vo>> calogJsonFromDb = getCategoriesDb();
            //3、将查到的数据放入缓存,将对象转为json放在缓存中
            String s = JSON.toJSONString(calogJsonFromDb);
            stringRedisTemplate.opsForValue().set("catalogJSON",s,1, TimeUnit.DAYS);
        }
        System.out.println("直接取的缓存数据");
        //转为指定的对象
        Map<String, List<Catalog2Vo>> result = JSON.parseObject(catalogJSON,new TypeReference<Map<String, List<Catalog2Vo>>>(){});
        return result;
    }


  //从数据库中查出三级分类
    private  Map<String, List<Catalog2Vo>> getCategoriesDb() {
        synchronized (this){
            //得到锁以后,应该再去缓存中确定一次,如果缓存中没有需要继续查询
            String catalogJSON = stringRedisTemplate.opsForValue().get("catalogJSON");
            if(!StringUtils.isEmpty(catalogJSON)){
                //缓存中存在数据、直接返回
                Map<String, List<Catalog2Vo>> result = JSON.parseObject(catalogJSON,new TypeReference<Map<String, List<Catalog2Vo>>>(){});
                return result;

            }

            System.out.println("缓存中没有数据,查询了数据库");
            //优化业务逻辑,仅查询一次数据库
            List<CategoryEntity> categoryEntities = this.list();
            //查出所有一级分类
            List<CategoryEntity> level1Categories = getCategoryByParentCid(categoryEntities, 0L);
            Map<String, List<Catalog2Vo>> listMap = level1Categories.stream().collect(Collectors.toMap(k->k.getCatId().toString(), v -> {
                //遍历查找出二级分类
                List<CategoryEntity> level2Categories = getCategoryByParentCid(categoryEntities, v.getCatId());
                List<Catalog2Vo> catalog2Vos=null;
                if (level2Categories!=null){
                    //封装二级分类到vo并且查出其中的三级分类
                    catalog2Vos = level2Categories.stream().map(cat -> {
                        //遍历查出三级分类并封装
                        List<CategoryEntity> level3Catagories = getCategoryByParentCid(categoryEntities, cat.getCatId());
                        List<Catalog2Vo.Catalog3Vo> catalog3Vos = null;
                        if (level3Catagories != null) {
                            catalog3Vos = level3Catagories.stream()
                                    .map(level3 -> new Catalog2Vo.Catalog3Vo(level3.getParentCid().toString(), level3.getCatId().toString(), level3.getName()))
                                    .collect(Collectors.toList());
                        }
                        Catalog2Vo catalog2Vo = new Catalog2Vo(v.getCatId().toString(), cat.getCatId().toString(), cat.getName(), catalog3Vos);
                        return catalog2Vo;
                    }).collect(Collectors.toList());
                }
                return catalog2Vos;
            }));
            return listMap;

        }

    }

使用jmeter对其进行压测

在这里插入图片描述

查看控制台情况,理想情况是数据库只查询一次。实际上查询了多次,出现这个问题的原因就是一个用户查询完数据后,就释放了锁。还未将数据写入缓存的时候,第二个用户又拿到了锁。这个时候缓存中还未进行数据缓存,导致再次查询数据库。需要优化代码逻辑

在这里插入图片描述

代码二(问题解决)

优化代码逻辑,压测过程同上。

在这里插入图片描述

在这里插入图片描述

6、新问题

本地锁在分布式情况下是锁不住的

7、分布式锁

待编辑

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Attention is all your need——Transformer论文

摘要 此序列转录模型仅仅依赖于注意力机制&#xff0c;而不使用循环或者是卷积&#xff0c;将循环全部换成了multi-headed self- attention 介绍 RNN的特点、并行程度低。 Attention在RNN上的应用。 引入注意力机制&#xff0c;提高并行度。 背景 使用卷积对长的序列难以…

3D开发工具HOOPS最新解析合集,助力实现web端高性能模型渲染

一、3D技术为创新提供强大助力 不管您想搭建桌面、WEB或者移动端APP应用&#xff0c;技术领先全球的HOOPS Platform组件都可以为您提供弹性的3D集成架构&#xff0c;同时&#xff0c;一批可信任的工业领域3D技术专家也将为您提供技术支持服务。 如果您的客户期望有一种在多个…

第三十一天 Linux介绍和基础命令

目录 1.前言 1.1 什么是Linux 1.2 为什么要学Linux 1.3 学完Linux能干什么 2.Linux简介 2.1 主流操作系统 2.2 Linux发展历史 3. Linux安装 3.1 安装方式介绍 3.2 安装VMware 3.3 安装Linux 3.4 网卡设置 3.5 安装SSH连接工具 3.6 Linux目录结构 4.Linux常用命令…

DHTMLX Gantt入门使用教程【引入】:如何开始使用 dhtmlxGantt

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求&#xff0c;具备完善的甘特图图表库&#xff0c;功能强大&#xff0c;价格便宜&#xff0c;提供丰富而灵活的JavaScript API接口&#xff0c;与各种服务器端技术&am…

Excel玩转自然语言查询

ChatGPT火出圈&#xff0c;人类被人工智能替代又成为热门话题。有人欢喜&#xff0c;有人忧&#xff0c;也有人不以为意&#xff0c;觉得离自己工作远着呢&#xff0c;比如现在是用Excel做报表&#xff0c;有本事你动动嘴就直接把Excel里面的数据查询出来啊。 你可别说&#xf…

【题解】P4055 [JSOI2009] 游戏

link 题目大意 题目说得比较清楚。 题解 前置知识&#xff1a;二分图最大匹配、基础博弈论。 每个点只能走一次的四联通点阵&#xff0c;可以想到二分图匹配。 将其套路地奇偶分点&#xff0c;相邻两点连边&#xff08;显然不能为 #&#xff09;。 先求一个最大匹配。 …

5G/V2X赛道「重启」

在提升高阶智能驾驶安全性和感知冗余能力的道路上&#xff0c;除了激光雷达、高精度地图及定位&#xff0c;还有一项技术可能即将掀起一场新的风暴。 就在今年3月&#xff0c;作为全球通信领域的年度风向标 — 2023世界移动通信大会&#xff08;MWC&#xff09;上&#xff0c;…

基于html+css的盒子展示6

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

第七回:如何使用GirdView Widget

文章目录概念介绍使用方法示例代码经验总结我们在上一章回中介绍了Image Widget,本章回中将介绍 GirdView这种Widget&#xff0c;闲话休提&#xff0c;让我们一起Talk Flutter吧。概念介绍 在Flutter中使用GirdView表示网格状的布局&#xff0c;类似日常办公中使用的Excel,它和…

win10彻底永久关闭自动更新【亲测有效】

一、禁用Windows Update服务 1、同时按下键盘 Win R&#xff0c;打开运行对话框&#xff0c;然后输入命令 services.msc &#xff0c;点击下方的“确定”打开服务&#xff0c;如下图所示。 2、找到 Windows Update 这一项&#xff0c;并双击打开&#xff0c;如图所示。 3、右击…

MySQL-中间件mycat(二)

目录 &#x1f341;部署主从复制 &#x1f341;mycat读写分离 &#x1f342;修改配置文件 &#x1f342;设置balance与writeType &#x1f342;设置switchType与slaveThreshold &#x1f342;启动程序 &#x1f342;验证读写分离 &#x1f341;垂直拆分-分库 &#x1f342;实现…

openvpn (用户名密码模式)

目录 一、介绍 1、定义 2、原理 3、加密和身份验证 二、在centos 7.5上搭建openvpn 1、安装openvpn 和easy-rsa&#xff08;该包用来制作ca证书&#xff09; 2、配置/etc/openvpn/ 目录 3、创建服务端证书及key 4、创建客户端证书 5、把服务器端必要文件放到etc/openvpn/ 目录下…

融云出海赋能会干货回顾 | 用户增长、场景玩法、安全合规实用指南

近期&#xff0c;“纵浪潜海 2023 融云社交泛娱乐出海赋能会”在上海、广州相继举行。移步【融云全球互联网通信云】&#xff0c;回复【出海】获取PPT。 作为更专业的出海服务商&#xff0c;融云联合多家出海服务企业&#xff0c;从热门出海地区的特性洞察、玩法解决方案、技…

ElasticSearch索引文档写入和近实时搜索

一、基本概念 1.Segments In Lucene 众所周知&#xff0c;ElasticSearch存储的基本单元Shard&#xff0c;ES中一个Index可能分为多个Shard&#xff0c;事实上每个Shard都是一个Lucence的Index&#xff0c;并且每个Lucene Index由多个Segment组成&#xff0c;每个Segment事实上…

关键词词库制作-搜索词分析工具

关键词词库制作 关键词词库是一种帮助SEO和SEM优化的工具&#xff0c;它可以帮助您确定关键词的流行程度、竞争程度、搜索意图和其他相关信息等等。以下是一些关键词词库制作的方法&#xff1a; 收集关键词&#xff1a;首先需要收集相关的关键词&#xff0c;这可能涉及到您的业…

Transformer中的注意力机制及代码

文章目录1、简介2、原理2.1 什么是注意力机制2.2 注意力机制在NLP中解决了什么问题2.3 注意力机制公式解读2.4 注意力机制计算过程3、单头注意力机制与多头注意力机制4、代码4.1 代码14.2 代码21、简介 最近在学习transformer&#xff0c;首先学习了多头注意力机制&#xff0c…

[ vulnhub靶机通关篇 ] 渗透测试综合靶场 DC-5 通关详解 (附靶机搭建教程)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

[Data structure]队列环形队列 | 一文带你彻底搞懂队列和环形队列(内附详细图解和代码实现)

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;数据结构。数据结构专栏主要是在讲解原理的基础上拿Java实现 ⭐如果觉得文章写的不错&#xff0c;欢迎点个关注一…

淘宝/天猫店铺订单数据导出、销售报表、数据分析

最近有厂商提出想把天猫店铺的数据拿到后台ERP管理系统中&#xff0c;并能实现线下打印电子面单功能。接手这个需求按照度娘给的指引&#xff0c;申请天猫开发者帐号&#xff0c;但是。。。大厂把订单传送接口关了&#xff0c;只对厂商自研软件开放&#xff0c;还需要租用聚石塔…

「MongoDB」时序数据库和MongoDB第二部分-模式设计最佳实践

在上一篇博客文章时间序列数据与MongoDB&#xff1a;第一部分-简介中&#xff0c;我们介绍了时间序列数据的概念&#xff0c;然后介绍了一些可以用于帮助收集时间序列应用程序需求的发现问题。对这些问题的回答有助于指导支持大容量生产应用程序部署所需的模式和MongoDB数据库配…