【黑马点评优化】之使用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 {

    @Resource
    private 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中查询。
在这里插入图片描述

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

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

相关文章

大有期货携手云轴科技ZStack 获“鼎新杯”数字化转型典型案例二等奖

近日&#xff0c;由中国通信标准化协会主办、中国信息通信研究院&#xff08;简称“中国信通院”&#xff09;承办、中国通信企业协会支持的“2024数字化转型发展大会”在北京召开。本届大会以“拥抱数智化无限可能”为主题&#xff0c;会上公布了第三届“鼎新杯”数字化转型应…

Centos 7.9NFS搭建

原创作者&#xff1a;运维工程师 谢晋 Centos 7.9NFS搭建 NFS服务端安装客户机访问共享配置 NFS服务端安装 SSH连接系统登录到服务端安装nfs服务 # yum -y install nfs-utils2. 安装完成后&#xff0c;查看需要共享的目录&#xff0c;这边共享的是/home目录&#xff0c;如…

Selenium - 用这个力量做任何你想做的事情

Chrome DevTools 简介 Chrome DevTools 是一组直接内置在基于 Chromium 的浏览器&#xff08;如 Chrome、Opera 和 Microsoft Edge&#xff09;中的工具&#xff0c;用于帮助开发人员调试和研究网站。 借助 Chrome DevTools&#xff0c;开发人员可以更深入地访问网站&#xf…

苹果正式宣布:iPhone全面开放近场通信(Near Field Communication,简称NFC)【使用安全元件提供app内NFC数据交换功能】

文章目录 引言I iPhone的NFC功能开发者用户数据交换的体验革新安全与隐私II 知识扩展:近场通信(NFC)技术钱包NFC开关打开读取NFC标签(NFC tags )权限demo引言 2014年iPhone 6开始,苹果首次引入了NFC功能,但最初只允许自家的Apple Pay进行移动支付。慢慢地适配了交通卡,增…

RAG拉满-上下文embedding与大模型cache

无论怎么选择RAG的切分方案&#xff0c;仍然切分不准确。 最近&#xff0c;anthropics给出了补充上下文的embedding的方案&#xff0c;RAG有了新的进展和突破。 从最基础的向量查询&#xff0c;到上下文embedding&#xff0c;再到rerank的测试准确度都有了明显的改善&#xf…

Excel:vba实现合并工作簿中的表

A、B、C这三个工作簿的数据都在sheet1&#xff0c;表头一样 Sub MergeWorkbooks()Dim FolderPath As StringDim FileName As StringDim wb As WorkbookDim ws As WorksheetDim mainWb As WorkbookDim mainWs As WorksheetDim lastRow As LongDim lastcol As LongDim pasteRang…

双足机器人远程操作与动态运动同步研究

在当前的机器人技术中&#xff0c;双足机器人因其能够在复杂环境中灵活行动而备受关注。随着技术的进步&#xff0c;研究者们致力于开发能够与人类操作员实现高效同步的双足机器人&#xff0c;特别是在应对自然灾害或人为危险等紧急情况下的应用。 项目背景 尽管人工智能领域取…

Missing classes detected while running R8报错解决方案

Android 打包release版本时报错如下&#xff1a; > Task :printlib:minifyReleaseWithR8 FAILED AGPBI: {"kind":"error","text":"Missing classes detected while running R8. Please add the missing classes or apply additional ke…

在限制条件下求1+2+3+...+n

一&#xff1a;题目 二&#xff1a;代码 前提&#xff1a; A&#xff1a;静态成员和静态函数的性质 1.静态成员为所有类对象所共享&#xff0c;不属于某个具体的对象&#xff0c;存放在静态区 2. 静态成员变量必须在类外定义&#xff0c;定义时不添加static关键字&#xff0…

大模型生图安全疫苗注入赛题解析(DataWhale组队学习)

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年10月实践赛的大模型生图安全疫苗注入赛道&#xff1b;本文主要整理本次赛事的基本流程和优化方法。&#x1f495;&#x1f495;&#x1f60a; 一…

使用node.js控制CMD命令——修改本机IP地址

设置每次打开cmd命令行窗口都是以管理员身份运行&#xff1a; 1. 按下Ctrl Shift Esc键组合&#xff0c;打开任务管理器。 2. 在任务管理器中&#xff0c;点击“文件”菜单&#xff0c;选择“运行新任务”。 3. 在“创建新任务”对话框中&#xff0c;输入cmd&#xff0c;勾…

1.2024.10.17

2024.10.17 总体规划 总体规划 写这个合集的原因 记录自己入行之前成长过程。本人菜鸟一枚&#xff0c;大佬不喜勿喷。 目前的规划 更新频率 尽量一天一更&#xff0c;会更新之前发布的笔记&#xff0c;争取笔记更加完善。 学习方法 目标 通过面试&#xff0c;成功入行嵌…

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——14.哈希(1)

移情别恋c ദ്ദി˶&#xff70;̀֊&#xff70;́ ) ——14.哈希(1) unordered系列关联式容器 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到 l o g 2 N log_2 N log2​N&#xff0c;即最差情况下需要比较红黑树的高度次…

新兴的安全职业挑战

我们经常与安全专业人士交谈&#xff0c;他们希望在努力提升职业发展的同时提高自己的价值并克服组织内部的挑战。在这些谈话中&#xff0c;花费大量时间讨论公司未来将面临的安全问题并不罕见。 安全领导者希望为问题制定计划并获得领导层对其计划的支持。这通常意味着实施修…

【RoadRunner】自动驾驶模拟3D场景构建 | 软件简介与视角控制

&#x1f4af; 欢迎光临清流君的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落 &#x1f4af; &#x1f525; 个人主页:【清流君】&#x1f525; &#x1f4da; 系列专栏: 运动控制 | 决策规划 | 机器人数值优化 &#x1f4da; &#x1f31f;始终保持好奇心&…

IDEA下载安装

文章目录 1、下载安装包2、安装IDEA3、全局配置4、安装插件5、关闭合并菜单栏 1、下载安装包 IDEA官网下载最新IDEA。 上面的ULtimate是旗舰版&#xff0c;试用30天&#xff0c;之后是需要收费的&#xff0c;下面黑色区域的Community是社区版&#xff0c;功能不如旗舰版丰富&a…

nuScenes数据集使用的相机的外参和内参

因为需要用不同数据集测试对比效果&#xff0c;而一般的模型代码里实现的检测结果可视化都是使用open3d的Visualizer在点云上画的3d框&#xff0c;展示出来的可视化效果很差&#xff0c;可能是偷懒&#xff0c;没有实现将检测结果投影到各相机的图像上&#xff0c;所以检测效果…

删除链表的倒数第 N 个结点 | LeetCode-19 | 双指针 | 递归 | 栈 | 四种方法

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 这道题还可以用递归法&#xff0c;你想到了吗&#xff1f;毛毛张介绍四种方法 LeetCode链接&#xff1a;19. 删除链表的倒数第 N 个结点 1.题目描述 给你一个链表&a…

【机器学习(十三)】机器学习回归案例之股票价格预测分析—Sentosa_DSML社区版

文章目录 一、背景描述二、Python代码和Sentosa_DSML社区版算法实现对比(一) 数据读入(二) 特征工程(三) 样本分区(四) 模型训练和评估(五) 模型可视化 三、总结 一、背景描述 股票价格是一种不稳定的时间序列,受多种因素的影响。影响股市的外部因素很多,主要有经济因素、政治因…

C++11新特性(4)

目录 1.包装器 2.线程库 2.1thread类的简单介绍 2.2线程函数参数 2.3原子性操作库(atomic) 2.4lock_guard与unique_lock 2.5mutex的种类 1. std::mutex 2. std::recursive_mutex 3. std::timed_mutex 4. std::recursive_timed_mutex 2.6lock_guard 2.7unique_lock 3.支持两个线…