【黑马点评优化】之使用Caffeine+Redis实现应用级二层缓存

【黑马点评优化】之使用Caffeine+Redis实现应用级二层缓存

    • 1 缓存雪崩定义及解决方案
    • 2 为什么要使用多级缓存
    • 3 Redis+Caffeine实现应用层二级缓存原理
    • 4 利用Caffeine+Redis解决Redis突然宕机导致的缓存雪崩问题
      • 4.1 pom.xml文件引入相关依赖
      • 4.2 本地缓存配置类
      • 4.3 修改ShopServiceImpl中的queryById方法
    • 5 测试

在这里修改一下黑马点评2商户查询的方法。使用Redis+Caffeine实现应用层二级缓存来解决缓存雪崩 的问题。
添加Caffeine的过程参考博客如下:
SpringBoot 集成 Caffeine、Redis实现双重缓存方式(-)caffeine redis-CSDN博客

1 缓存雪崩定义及解决方案

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。
解决方案:
● 给不同的Key的TTL添加随机值 (同一时段,所以给不同key设置不同的TTL)
● 利用Redis集群提高服务的可用性
● 给缓存业务添加降级限流策略 (微服务)
● 给业务添加多级缓存

2 为什么要使用多级缓存

如果只使用redis来做缓存我们会有大量的请求到redis,但是每次请求的数据都是一样的,假如这一部分数据就放在应用服务器本地,那么就省去了请求redis的网络开销,请求速度就会快很多;
如果只使用Caffeine来做本地缓存,我们的应用服务器的内存是有限,并且单独为了缓存去扩展应用服务器是非常不划算。所以,只使用本地缓存也是有很大局限性的;
因此在项目中,我们可以将热点数据放本地缓存,作为一级缓存,将非热点数据放redis缓存,作为二级缓存,减少Redis的查询压力。

使用流程大致如下:

  • 首先从一级缓存(caffeine-本地应用内)中查找数据;
  • 如果没有的话,则从二级缓存(redis-内存)中查找数据;
  • 如果还是没有的话,再从数据库(数据库-磁盘)中查找数据;

3 Redis+Caffeine实现应用层二级缓存原理

Redis 作为分布式缓存:

  • Redis 具有高性能、丰富的数据结构和可扩展性,适合作为分布式缓存存储大量的数据。它可以在多服务器环境下共享缓存数据,提高系统的整体性能。
  • 可以根据数据的特点选择合适的数据结构来存储数据,如使用哈希表存储对象、使用有序集合进行排行榜等操作。
  • 配置 Redis 的持久化机制,以防止数据丢失。同时,考虑使用 Redis 的集群或主从复制来提高可用性和可扩展性。

Caffeine 作为本地缓存:

  • Caffeine 是一个高效的本地缓存库,可以在应用程序内部实现缓存,减少对外部缓存服务的依赖,提高缓存的访问速度。
  • Caffeine 支持自动过期功能,可以根据设定的时间自动清除过期的缓存数据,减少内存占用。
  • 可以根据数据的访问频率和大小来调整 Caffeine 的缓存配置,如缓存的大小、过期时间等。
    实现二级缓存架构

数据存储流程:

  • 当应用程序需要访问数据时,首先从 Caffeine 本地缓存中查找数据。如果数据在 Caffeine 中存在,则直接返回数据,无需进一步访问 Redis 或数据库
  • 如果数据不在 Caffeine 中,则从 Redis 分布式缓存中查找数据。如果数据在 Redis 中存在,则将数据加载到 Caffeine 中,并返回数据给应用程序。
  • 如果数据不在 Redis 中,则从数据库中读取数据,并将数据同时存储到 Redis 和 Caffeine 中,然后返回数据给应用程序。

数据更新流程:

  • 当数据在数据库中被更新时,需要同时更新 Redis 和 Caffeine 中的缓存数据,以保证数据的一致性
  • 可以采用先更新数据库,然后删除 Redis 中的对应数据,让后续的访问从数据库中重新读取数据并更新到 Redis 和 Caffeine 中的方式来实现数据的更新。这种方式被称为 Cache Aside 模式。

缓存过期策略:

  • 对于 Caffeine 本地缓存,可以设置自动过期时间,根据数据的变化频率和访问频率来调整过期时间,以避免内存占用过高。
  • 对于 Redis 分布式缓存,可以根据业务需求设置合理的过期时间,或者采用主动更新的方式来保证缓存数据的有效性。

4 利用Caffeine+Redis解决Redis突然宕机导致的缓存雪崩问题

需求:修改根据id查询商铺的业务,基于二级缓存方式来解决缓存雪崩问题。
思路分析:当用户开始查询时,先查询本地缓存Caffeine,判断是否命中,如果没有命中则查询Redis,命中则直接返回。

在这里插入图片描述

4.1 pom.xml文件引入相关依赖

        <!--引入本地缓存Caffine--><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.9.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency>

4.2 本地缓存配置类

Config目录下新建本地缓存配置类,LocalCacheConfiguration

package com.hmdp.config;import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;/*** 本地缓存Caffeine配置类*/
@Configuration
public class LocalCacheConfiguration {@Bean("localCacheManager")public Cache<String, Object> localCacheManager() {return Caffeine.newBuilder()//写入或者更新5s后,缓存过期并失效, 实际项目中肯定不会那么短时间就过期,根据具体情况设置即可.expireAfterWrite(120, TimeUnit.SECONDS)// 初始的缓存空间大小.initialCapacity(50)// 缓存的最大条数,通过 Window TinyLfu算法控制整个缓存大小.maximumSize(500)//打开数据收集功能.recordStats().build();}}

4.3 修改ShopServiceImpl中的queryById方法

public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Resourceprivate Cache<String,Object> caffeineCache;//    @Cacheable(value = "shop",key = "#id")/public Result queryById(Long id){//1.从Caffeine中查询数据Object o = caffeineCache.getIfPresent(CACHE_SHOP_KEY + id);if(Objects.nonNull(o)){log.info("从Caffeine中查询到数据...");return Result.ok( o);}//缓存穿透Shop shop = cacheClient.queryWithPassThrough(CACHE_SHOP_KEY,id,Shop.class,this::getById,CACHE_SHOP_TTL,TimeUnit.MINUTES);if(shop != null){log.info("从Redis中查到数据");caffeineCache.put(CACHE_SHOP_KEY+id,shop);}if(shop == null){return Result.fail("店铺不存在!");}//7.返回数据return Result.ok(shop);}
}
  • caffeineCache.put(user.getId(), user):保存本地缓存;
  • caffeineCache.invalidate(id):移除指定的本地缓存;
  • caffeineCache.getIfPresent(id): 从本地缓存中获取值,如果缓存中不存指定的值,则方法将返回 null;
  • caffeineCache.get(id, Function<>): 从本地缓存中获取值,该方法还支持将一个参数为 key 的 Function 作为参数传入。如果缓存中不存在该 key,则该函数将用于提供默认值,该值在计算后插入缓存中,如果缓存的元素无法生成或者在生成的过程中抛出异常而导致生成元素失败,则返回null。

5 测试

运行启动类,使用前后端联调来测试查询商铺信息功能。运行结果如下,首次查询Caffeine中没有数据,所以输出从Redis中查询,第二次查询相同店铺时,从Caffeine中查询。
在这里插入图片描述

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

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

相关文章

UE5 使用Animation Budget Allocator优化角色动画性能

Animation Budget Allocator是UE内置插件&#xff0c;通过锁定动画系统所占CPU的预算&#xff0c;在到达预算计算量时对动画进行限制与优化。 开启Animation Budget Allocator需要让蒙皮Mesh使用特定的组件&#xff0c;并进行一些编辑器设置即可开启。 1.开启Animation Budget…

Tailwind Starter Kit 一款极简的前端快速启动模板

Tailwind Starter Kit 是基于TailwindCSS实现的一款开源的、使用简单的极简模板扩展。会用Tailwincss就可以快速入手使用。Tailwind Starter Kit 是免费开源的。它不会在原始的TailwindCSS框架中更改或添加任何CSS。它具有多个HTML元素&#xff0c;并附带了ReactJS、Vue和Angul…

k8s中的微服务

一、什么是微服务 用控制器来完成集群的工作负载&#xff0c;那么应用如何暴漏出去&#xff1f;需要通过微服务暴漏出去后才能被访问 Service是一组提供相同服务的Pod对外开放的接口。 借助Service&#xff0c;应用可以实现服务发现和负载均衡。 service默认只支持4层负载均…

二叉树与堆讲解

目录 1.树的概念及结构 1.树的概念 2.树的相关概念 3.树的表示 2.二叉树 1.概念 2.特殊的二叉树 1.满二叉树 2.完全二叉树 3.二叉树的性质 4.二叉树的存储结构 1.顺序结构 2.链式存储 3.堆 1.堆的概念及结构 2.堆的实现 1.堆的创建 2.堆的初始化&#xff08;H…

Spring Boot知识管理:跨平台集成方案

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

STM32 407 RS485通信实现数据收发【我的创作纪念日】

1. 前言 本例中的485驱动&#xff0c;基于标准库编写&#xff0c;不是HAL库&#xff0c;请大家注意。 最近搞嵌入式程序&#xff0c;踩了不少坑&#xff0c;这里统一记录一下。 2. 收获 1.串口通信&#xff0c;数据是一个字节一个字节的发送&#xff0c;对方收到的数据是放在…

【消息队列】Kafka从入门到面试学习总结

国科大学习生活&#xff08;期末复习资料、课程大作业解析、大厂实习经验心得等&#xff09;: 文章专栏&#xff08;点击跳转&#xff09; 大数据开发学习文档&#xff08;分布式文件系统的实现&#xff0c;大数据生态圈学习文档等&#xff09;: 文章专栏&#xff08;点击跳转&…

小米电机与STM32——CAN通信

背景介绍&#xff1a;为了利用小米电机&#xff0c;搭建机械臂的关节&#xff0c;需要学习小米电机的使用方法。计划采用STM32驱动小米电机&#xff0c;实现指定运动&#xff0c;为此需要了解他们之间的通信方式&#xff0c;指令写入方法等。花了很多时间学习&#xff0c;但网络…

【Next.js 项目实战系列】05-删除 Issue

原文链接 CSDN 的排版/样式可能有问题&#xff0c;去我的博客查看原文系列吧&#xff0c;觉得有用的话&#xff0c;给我的库点个star&#xff0c;关注一下吧 上一篇【Next.js 项目实战系列】04-修改 Issue 删除 Issue 添加删除 Button​ 本节代码链接 这里我们主要关注布局…

类和对象的认识

类&#xff1a;类是用来描述一个对象的&#xff0c;在java中万物皆对象&#xff0c;通过对类的抽象&#xff0c;类有哪些属性和行为&#xff0c;将这些抽象出来就是类。比如&#xff1a;狗&#xff0c;有名字&#xff0c;年龄&#xff0c;要吃饭的行为等等&#xff0c;将这些动…

仓储管理系统原型图移动端(WMS),出入库管理、库存盘点、库存调拨等(Axure原型、Axure实战项目)

仓储管理系统原型图移动端 Warehouse Management System Prototype 仓储管理系统原型图移动端是一个以图形化方式展示系统移动端界面和功能的原型设计图。原型图展示和说明系统移动端的功能和界面布局&#xff0c;为相关利益方提供一个直观的视觉化展示&#xff0c;帮助他们更…

RAG(检索增强生成)面经(1)

1、RAG有哪几个步骤&#xff1f; 1.1、文本分块 第一个步骤是文本分块&#xff08;chunking&#xff09;&#xff0c;这是一个重要的步骤&#xff0c;尤其在构建与处理文档的大型文本的时候。分块作为一种预处理技术&#xff0c;将长文档拆分成较小的文本块&#xff0c;这些文…

Android中的内容提供者

目录 1.创建内容提供者 1--手动创建一个Android应用程序 2--创建自定义的内容提供者 2.访问其他应用程序 1. 解析URI 2. 查询数据 3. 遍历查询结果 3)案例:读取手机通信录 1.声明权限 2.activity_main.xml文件内容 3.my_phone_list.xml文件内容 4.定义PhoneInfo实体 5.定义MyPh…

线程异步和通信(promise和future)

线程异步和通信&#xff08;promise和future&#xff09; #include <thread> #include <iostream> #include <future> #include <string> using namespace std;void TestFuture(promise<string> p)//线程函数 {cout << "begin TestFu…

JAVA就业笔记7——第二阶段(4)

课程须知 A类知识&#xff1a;工作和面试常用&#xff0c;代码必须要手敲&#xff0c;需要掌握。 B类知识&#xff1a;面试会问道&#xff0c;工作不常用&#xff0c;代码不需要手敲&#xff0c;理解能正确表达即可。 C类知识&#xff1a;工作和面试不常用&#xff0c;代码不…

绘制YOLOv11模型在训练过程中,精准率,召回率,mAP_0.5,mAP_0.5:0.95,以及各种损失的变化曲线

一、本文介绍 本文用于绘制模型在训练过程中,精准率,召回率,mAP_0.5,mAP_0.5:0.95,以及各种损失的变化曲线。用以比较不同算法的收敛速度,最终精度等,并且能够在论文中直观的展示改进效果。支持多文件的数据比较。 专栏目录:YOLOv11改进目录一览 | 涉及卷积层、轻量化…

spring task的使用场景

spring task 简介 spring task 是spring自带的任务调度框架按照约定的时间执行某个方法的工具&#xff0c;类似于闹钟 应用场景 cron表达式 周和日两者必定有一个是问号 简单案例 使用步骤 demo Component注解表示这是一个Spring的组件&#xff0c;会被Spring容器扫描到&#…

全面超越Spark,Clickhouse,比 Spark 快 900%,基于云器Lakehouse构建新一代一体化数据平台

人工智能的迅速发展正在改变着我们的世界&#xff0c;对于大数据企业来说更是如此。 在大语言模型的引领下&#xff0c;数据平台领军企业 Databricks 和 Snowflake 的未来正在被重新书写。这两家企业在不久前的发布会上强调了大语言模型和 AI 能力的重要性&#xff0c;试图通过…

[单master节点k8s部署]41.部署springcloud项目

在之前的文章中我们配置了mysql和harbor&#xff0c;现在我们可以将一个springcloud部署在k8s集群中了。 项目概述 这个springcloud项目将采用maven进行打包部署。首先安装maven&#xff1a; yum install java-1.8.0-openjdk maven-3.0.5* -y 然后将该项目上传到k8s集群的m…

ANSYS 2024 R2设置中文

ANSYS 2024 R2设置中文 打开ANSYS Workbench R2软件依次点击Tools、Options 在弹出的Options选项卡中选择Regional and Language Options项&#xff0c;选择Language为Chinese然后点击OK 重启软件即可切换为中文界面