缓存雪崩解决方案:二级缓存VS随机TTL

背景

在学习缓存雪崩的时候,了解到有二级缓存和随机TTL两个解决方案,但是在学习之后,个人认为二级缓存本质上还是利用两层缓存的过期时间不一致来实现缓存过期时间随机化,这不就是和随机TTL一样吗,故有了这篇思考,如有不对,欢迎指正

缓存雪崩是什么

缓存雪崩指的是大量的缓存同时失效(过期)导致大量的请求直接到了数据库,数据库瞬间受到了很大的压力,可能导致系统崩溃

或者是缓存层直接不提供服务宕机导致大量请求直接打到数据库上,使得数据库承受很大压力

其中缓存雪崩解决方案有多种,其中两种为

  • 二级缓存
  • 设置随机ttl(随机过期时间)

二级缓存是什么?

二级缓存指的是将两个不同层次的缓存结合起来使用,是一种组合型分组的缓存结构,最常见的就是Redis+本地缓存(如Caffeine)。目的是通过分层设计,在内存与持久化缓存之间分担压力,提高系统的容错能力与性能。(一般是采取热点数据存储到本地缓存,非热点数据存储到redis种)

常见的一个请求流程图如下:

首先先查询一级缓存,随后如果读取不到的话就读取二级缓存,再没有就去数据库查询并且将找到的数据写入一二级缓存

代码示例

 // 根据店铺 ID 查询店铺信息public String queryShopById(Long id) {String cacheKey = CACHE_SHOP_KEY + id;// 1. 首先查询 Caffeine 本地缓存String shop = caffeineCache.getIfPresent(cacheKey);if (shop != null) {System.out.println("从Caffeine缓存中查询到数据...");return shop;}// 2. 如果 Caffeine 本地缓存没有,从 Redis 查询shop = redisTemplate.opsForValue().get(cacheKey);if (shop != null) {System.out.println("从Redis缓存中查询到数据...");// Redis 命中,放入 Caffeine 本地缓存caffeineCache.put(cacheKey, shop);return shop;}// 3. 如果 Redis 和 Caffeine 都没有,从数据库查询shop = getShopFromDatabase(id);if (shop != null) {// 数据库查询成功,将数据放入 Redis 和 Caffeine 缓存redisTemplate.opsForValue().set(cacheKey, shop, 10, TimeUnit.MINUTES);  // 设置 Redis 缓存有效期caffeineCache.put(cacheKey, shop);  // 将数据放入 Caffeine 本地缓存return shop;}return "店铺不存在";}

二级缓存如何解决缓存雪崩的问题

(1) 缓存过期时间不一致,避免大规模并发请求(核心)
  • 为了避免缓存雪崩问题,Redis 缓存和 Caffeine 缓存的过期时间可以设置不同,而且本地缓存 Caffeine 还支持自动清除过期的缓存。这种不同的过期策略可以避免大量缓存同时过期。
  • 避免全量缓存同时失效:通过设计合理的过期时间,避免 Redis 和 Caffeine 缓存同时在同一时刻过期。比如,Redis 缓存设置为较长的过期时间(例如 10 分钟),而 Caffeine 的过期时间较短(例如 1 分钟)。这样即使 Redis 缓存失效,本地缓存仍然能继续工作,避免了缓存雪崩的发生。(caffeine可以通过设置expireAfter:基于个性化定制的逻辑来实现过期处理,灵活设置过期时间)
(2) Redis 缓存失效时,Caffeine 能接管
  • Redis 缓存失效时,由于本地缓存(Caffeine)的存在,查询操作首先会尝试从 Caffeine 获取数据,这样能够在 Redis 缓存失效期间保证一定的服务可用性,并避免所有请求都落到数据库上。
(3) Caffeine 本地缓存减少对 Redis 的压力
  • Caffeine 作为本地缓存,存储的是每个节点本地的数据,能够极大地减少对 Redis 的访问。
  • 即使 Redis 缓存失效(比如 Redis 发生故障或缓存过期),本地缓存 Caffeine 仍然可以继续提供服务,避免了缓存失效后直接查询数据库的压力。

随机ttl是什么?

随机 TTL(Time to Live)是设置缓存过期时间的一种策略,它通过给每个缓存设置一个 随机的过期时间,来避免缓存过期时间集中在同一时刻。从而避免了大量缓存同时过期,避免了大量请求同时击中数据库的缓存雪崩问题。

一种常用的方案就是在集体的过期时间上各个添加一个随机的时长从而实现随机ttl

随机ttl如何解决的缓存雪崩?

即时多个原本的缓存项的原本的过期时间相同,经过随机化后,它们的实际过期时间就不同了,减少了集中过期概率

当缓存项过期,新的请求触发从数据库加载数据并更新缓存,避免了大规模同时从数据库加载数据

示例代码

public class CacheExample {private static final String CACHE_KEY = "shop_info:";private static final int MIN_TTL = 5; // 最小 TTL 时间(秒)private static final int MAX_TTL = 20; // 最大 TTL 时间(秒)private static Jedis jedis = new Jedis("localhost", 6379); // Redis 连接// 模拟查询数据库获取数据private static String queryDatabase(Long id) {return "Shop Info for ID: " + id;}// 获取缓存数据public static String getShopInfo(Long id) {String cacheKey = CACHE_KEY + id;// 尝试从 Redis 获取缓存数据String cachedData = jedis.get(cacheKey);if (cachedData != null) {System.out.println("从缓存获取数据: " + cachedData);return cachedData;}// 如果缓存不存在,查询数据库String data = queryDatabase(id);// 设置缓存时,使用随机的 TTL(过期时间)int ttl = new Random().nextInt(MAX_TTL - MIN_TTL + 1) + MIN_TTL;jedis.setex(cacheKey, ttl, data);System.out.println("从数据库获取数据并缓存: " + data);return data;}// 模拟调用缓存查询public static void main(String[] args) {// 查询 shop 1System.out.println(getShopInfo(1L));// 查询 shop 2System.out.println(getShopInfo(2L));}
}

但是,经过看过两种实现,其实仔细一看好像似乎随机TTL和二级缓存的本质都是避免缓存同时过期来解决缓存雪崩的问题,保证缓存不会大量同一时刻失效,从而减少数据库的访问压力,但是二者并非一致 

随机TTL VS 二级缓存

1. 随机 TTL 优势:

  • 简单实现:相比于二级缓存方案,随机 TTL 不需要引入额外的缓存系统,只需调整缓存的过期策略即可,配置和实现较为简单。
  • 降低缓存过期集中性:通过随机化每个缓存项的过期时间,解决了大量缓存同时过期的问题,减少了对数据库的压力。

2. 二级缓存优势:

  • 更高的可用性:二级缓存引入了本地缓存(如 Caffeine)和分布式缓存(如 Redis),即使 Redis 出现故障,本地缓存 Caffeine 仍然能继续提供数据服务,确保系统高可用。
  • 更高的性能:本地缓存 Caffeine 可以极大降低 Redis 的访问压力,提升系统响应速度。
  • 数据一致性和实时更新:二级缓存可以通过合理的缓存更新机制和缓存失效策略,保持数据的一致性和及时更新,避免缓存和数据库的不同步问题。

二者的核心区别:

缓存的可靠性和冗余

  • 随机ttl只是通过在缓存失效时间引入随机性避免缓存雪崩问题,但是这种方法只依赖单一缓存层,如果缓存层出现问题,整个缓存机制失效,所有请求直接访问数据库
  • 二级缓存而是通过两层缓存系统提高缓存可靠性和容错能力,即时一级缓存失效,应用依然能够依赖另外一层缓存提供数据,避免了对数据库的直接访问,意味着即使分布式缓存(如 Redis)失效,应用也可以通过本地缓存继续提供数据,保证系统的高可用性。

性能的优化:

本地缓存的延迟比redis更短,而且内存访问速度极快,本地缓存是 非常有效的性能优化手段

总结

虽然 随机 TTL二级缓存 都是解决 缓存雪崩 的有效手段,但它们的设计目标和适用场景有所不同。随机 TTL 简单有效,适用于单一缓存层的情况,尤其是 Redis。二级缓存通过结合 Redis 和本地缓存来增强系统的 容错性、高可用性、性能优化 ,适用于更复杂和高并发的场景。

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

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

相关文章

Android View事件分发机制深度解析

在Android面试中,关于View事件分发机制的考察往往不仅限于基础流程,更关注底层原理、性能优化和实际应用场景。以下是针对面试的全面回答策略: 一、基础回答框架 核心三要素: 传递流程 "事件分发遵循Activity → Window →…

2829. k-avoiding 数组的最小总和

2829. k-avoiding 数组的最小总和 题目链接:2829. k-avoiding 数组的最小总和 代码如下: class Solution { public:int minimumSum(int n, int k) {int m min(k / 2, n);return (m * (m 1) (k * 2 n - m - 1) * (n - m)) / 2;} };

phpStorm2021.3.3在windows系统上配置Xdebug调试

开始 首先根据PHP的版本下载并安装对应的Xdebug扩展在phpStorm工具中找到设置添加服务添加php web page配置完信息后 首先根据PHP的版本下载并安装对应的Xdebug扩展 我使用的是phpStudy工具,直接在php对应的版本中开启xdebug扩展, 并在php.ini中添加如下…

LabVIEW永磁同步电机性能测试系统

开发了一种基于LabVIEW的永磁同步电机(PMSM)性能测试系统的设计及应用。该系统针对新能源汽车使用的电机进行稳态性能测试,解决了传统测试方法成本高、效率低的问题,实现了测试自动化,提高了数据的准确性和客观性。 ​…

谷粒商城:Redisson

目录 Redisson 整合Redisson RLock RReadWriteLock RSemaphore RCountDownLatch 优化三级分类缓存 缓存一致性问题 双写模式 失效模式 脏数据解决 Redisson 提供redis分布式锁(Distributed locks with Redis)的java客户端 整合Redisson 引入 …

Linux系统调用编程

目录 一. 理解进程和线程的概念。并在Linux系统下进行相应操作 1.1概念 1.1.1进程(Process) 1.1.2 线程(Thread) 1.2操作 1.2.1用 ps -a 命令查看系统中各进程的编号pid 1.2.2用kill 命令终止一个进程pid 二. 解释Linux的“虚拟内存管理”,它与stm32中的 真…

25-智慧旅游系统(协同算法)三端

介绍 技术: 基于 B/S 架构 SpringBootMySQLLayuivue 环境: Idea mysql maven jdk1.8 node 管理端功能 首页展示图表:以数据可视化方式展示关键业务数据。 用户管理:管理系统用户,包括查看、编辑等操作。 供应商管…

【stm32--HAL库DMA+USART+空闲中断不定长收发数据】

串口通信-Hal库实现不定长度收发,DMAUSART DMA串口STM32CUBEMX配置(工程创建)基础配置时钟配置工程配置 代码编写现象 DMA 在正式配置之前,我们先来一起简单了解一下DMA。DMA(Direct Memory Access,直接内…

沉浸式体验测评|AI Ville:我在Web3小镇“生活”了一周

最近,我在朋友的推荐下,体验了 aivillebot 的项目。起初,我只是抱着试试看的心态,心想这不就是个 Web3 版的《星露谷物语》吗? 但是一周下来,我发现这个虚拟小镇也没那么简单——里面的居民不是目前端游或链…

FPGA学习-基于 DE2-115 板的 Verilog 分秒计数器设计与按键功能实现

一、核心功能设计 按键暂停/继续:通过KEY1控制计时状态 按键消抖处理:20ms消抖周期消除机械抖动 硬件资源分配:符合DE2-115开发板引脚规范 二、核心模块实现详解 1. 顶层模块(counter) module counter(input CL…

后端开发 SpringBoot 工程模板

概述 本篇文章主要记录如何开发一个通用的 SpringBoot 工程开发框架的项目模板,这样后续需要开发项目时就可以直接开箱直用了,省区了很多重复步骤。 项目初始化 创建项目: 按照我的选项来选,然后点击 create,等待文…

OpenCv(五)——边缘检测

目录 边缘检测 一、sobel算子边缘检测 (1)原理 1、X轴方向的边缘检测 2、Y轴方向的边缘检测 (2)sobel算子参数 (3)X轴方向边缘检测代码演示 1、显示圆的图像 2、x方向上的边缘检测&#xf…

无人机数据链技术及运行方式详解!

一、无人机数据链技术要点 1. 通信传输技术 频段选择: 常用频段包括 L波段(1-2 GHz)、C波段(4-8 GHz)、Ku/K波段(12-40 GHz),不同频段在传输距离、带宽和抗干扰性间权衡。 低…

AI Agent 实战:搭建个人在线旅游助手

AI Agent 实战:搭建个人在线旅游助手 本次实验中,我们将继续探索 Agent 的提示词,学习更加规范的提示词撰写方法。 本实验中你将掌握的知识点 使用 Dify 构建 Agent 的方法结构化的提示词撰写技巧变量的使用方法 1. 准备 在新建 Agent 之…

检索增强生成(RAG):强化 AI 智能体的知识 “武装”

技术点目录 第一章、智能体(Agent)入门第二章、基于字节Coze 构建智能体(Agent)第三章、基于其他平台构建智能体(Agent)第四章、国内外智能体(Agent)经典案例详解第五章、大语言模型应用开发框架LangChain入门第六章、基于LangChain的大模型API接入第七章…

vscode 打开工程 看不到文件目录

vscode 打开工程 看不到文件目录 View->Explorer 快捷键:CtrlShiftE

厘米级定位赋能智造升级:品铂科技UWB技术驱动工厂全流程自动化与效能跃升”

在智能制造中的核心价值体现在‌高精度定位、流程优化、安全管理‌等多个维度,具体应用如下: 一、‌核心技术与定位能力‌ ‌厘米级高精度定位‌ UWB技术通过‌纳秒级窄脉冲信号‌(带宽超500MHz)实现高时间分辨率,结合…

getID3获取本地或远程视频时长

音频文件也可使用,使用ffmeg安装太复杂了 附ffmpeg方式:centos下安装ffmpeg_yum安装ffmpeg-CSDN博客 使用composer先安装 composer require james-heinrich/getid3 获取本地视频 //获取本地视频$video_path $_SERVER[DOCUMENT_ROOT].$params[video];…

10、Linux C 网络编程(完整版)

1、网络发展历史和分层 1.1 Internet 的历史 起源: 1957 年:苏联发射第一颗人造卫星 "Sputnik"。 1958 年:美国总统艾森豪威尔成立 DARPA(国防部高级研究计划署)。 1968 年:DARPA 提出 "…

前端:开源软件镜像站 / 清华大学开源软件镜像站 / 阿里云 / 网易 / 搜狐

一、理解开源软件镜像站 开源软件镜像是指开源软件在远程服务器上的备份副本,允许用户通过互联网快速下载和安装所需的软件。在国内,有多个知名的开源软件镜像站,为开发者提供稳定、快速的开源软件下载服务。 二、常见开源软件镜像站 序号…