Redis篇--常见问题篇2--缓存雪崩(过期时间分散,缓存预热,多级缓存)

embedded/2024/12/24 0:31:52/

1、概述

缓存雪崩是指在短时间内,大量的缓存同时失效或过期,导致大量的请求穿透到后端数据库或服务,从而引发系统负载骤增,甚至可能导致系统崩溃。这种情况通常发生在缓存的过期时间设置不合理时,所有缓存的过期时间相同,导致它们在同一时间点失效。

示意图:
在这里插入图片描述

2、解决方案

(1)、设置不同的过期时间(推荐)

为每个缓存项设置一个 随机的过期时间,而不是统一的过期时间。这样可以避免所有缓存项在同一时间点失效,分散了缓存失效的时间窗口,减少了对数据库的压力。
示例:

 // 设置随机化的 TTLint baseTtl = 60; // 基础 TTL 为 60 秒int randomOffset = new Random().nextInt(20); // 随机偏移0-19秒redisTemplate.opsForValue().set("key", "value", baseTtl + randomOffset, TimeUnit.SECONDS);

(2)、缓存预热

在系统启动时或定期进行缓存预热,提前加载或有策略的定期加载一些常用的数据库数据到缓存中,确保缓存中有足够的数据,减少缓存失效时的冲击。

(3)、多级缓存

使用多级缓存策略,例如:本地缓存+分布式缓存。当分布式缓存失效时,本地缓存可以继续提供服务,减少对数据库的直接访问。
应用:本地缓存(如Caffeine、Guava Cache)来缓存频繁访问的数据,同时使用分布式缓存(如Redis、Memcached)来存储全局共享的数据。
本地缓存的TTL可以设置得比分布式缓存更短,以减少对分布式缓存的依赖。

多级缓存示例(Caffine+Redis)
第一步:导入依赖

<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.9.0</version>
</dependency>

第二步:注入配置类

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic Cache<String,Object> caffeineCache() {    // 初始化注入CaffeineCache到容器return Caffeine.newBuilder().initialCapacity(100)  // 初始容量为100.maximumSize(1000)   // 最大存1000个key.expireAfterWrite(1, TimeUnit.MINUTES)   // 设置1分钟过期.build();}
}

第三步:测试类

import com.github.benmanes.caffeine.cache.Cache;
import com.zw.base.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;@RestController
@RequestMapping(value = "redis3", method = {RequestMethod.POST, RequestMethod.GET})
public class RedisController3 extends BaseController {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// 本地缓存CaffeineCache@Resourceprivate Cache<String, Object> caffeineCache;// 模拟数据库查询private Object queryFromDatabase(String key) {// 模拟数据库查询逻辑System.out.println("Querying from database for key: " + key);return null; // 假设数据库中没有该数据}/*** 获取数据,优先从本地缓存获取,其次从 Redis 获取,最后从数据库获取* @param key 数据的唯一标识* @return 数据*/@RequestMapping("/get")public Object getTest(String key) {// 1. 尝试从本地缓存获取Object cachedData = caffeineCache.getIfPresent(key);if (cachedData != null) {if ("NULL".equals(cachedData)) {return null; // 返回空对象}return cachedData;}// 2. 尝试从 Redis 获取cachedData = redisTemplate.opsForValue().get(key);if (cachedData != null) {if ("NULL".equals(cachedData)) {caffeineCache.put(key, "NULL"); // 将空对象放入本地缓存return null;}caffeineCache.put(key, cachedData); // 将数据放入本地缓存return cachedData;}// 3. 从数据库获取数据Object data = queryFromDatabase(key);if (data != null) {if (data != null) {// 更新本地缓存和 RediscaffeineCache.put(key, data.toString());redisTemplate.opsForValue().set(key, data, getRandomTtl(), TimeUnit.SECONDS);} else {// 缓存空对象caffeineCache.put(key, "NULL");redisTemplate.opsForValue().set(key, "NULL", 60, TimeUnit.SECONDS); // 空对象过期时间为 60 秒}}// 4. 返回旧的缓存数据(如果有)return caffeineCache.getIfPresent(key);}/*** 获取随机化的 TTL,避免所有缓存项在同一时间点失效** @return 随机化的 TTL(秒)*/private long getRandomTtl() {int baseTtl = 60; // 基础 TTL 为 60 秒int randomOffset = (int) (Math.random() * 10); // 随机偏移 0-9 秒return baseTtl + randomOffset;}
}

第四步:测试验证
可以正常查询有的值
在这里插入图片描述
没有的key直接返回null
在这里插入图片描述


http://www.ppmy.cn/embedded/148203.html

相关文章

机器学习之KNN算法

K-Nearest Neighbors (KNN) 是一种常见的机器学习算法&#xff0c;广泛应用于分类和回归问题。KNN是一种基于实例的学习方法&#xff0c;它利用训练数据集的实例来进行分类或回归预测。在KNN中&#xff0c;预测的结果依赖于距离度量函数计算出的最近邻实例的标签或值。下面我们…

基于大语言模型的多代理下一代制造系统能灵活动态管理制造资源的高效调度方法

摘要 论文地址&#xff1a;https://arxiv.org/pdf/2405.16887 随着生产率的提高&#xff0c;客户对多品种、小批量生产的需求也在不断增加&#xff0c;这反过来又对制造系统提出了更高的要求。由于这种需求&#xff0c;当生产任务频繁变化时&#xff0c;传统的制造系统往往无法…

TCP 与 UDP

TCP与UDP的区别分析 TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;是互联网协议族&#xff08;TCP/IP&#xff09;中的两种重要传输层协议。它们在数据传输的方式、特性以及应用场景方面存在显著差异。以下将从多个方面详细分析TCP与U…

workman服务端开发模式-应用开发-后端api推送修改二

需要修改两个地方&#xff0c;第一个是总控制里面的续token延时&#xff0c;第二个是操作日志记录 一、总控续token延时方法 在根目录下app文件夹下controller文件夹下Base.php中修改isLoginAuth方法&#xff0c;具体代码如下&#xff1a; <?php /*** 总控制* User: 龙哥…

web3跨链预言机协议-BandProtocol

项目简介 Band Protocol 项目最初于 2017年成立并建立在 ETH 之上。后于2020年转移到了 Cosmos 网络上&#xff0c;基于 Cosmos SDK 搭建了一条 Band Chain 。这是一条 oracle-specific chain&#xff0c;主要功能是提供跨链预言机服务。Cosmos生态上第一个&#xff0c;也是目…

redis数据转移

可能有时候因为硬件的原因我们我们需要更换服务器&#xff0c;如果更换服务器的话&#xff0c;那我们redis的数据该怎样转移呢&#xff0c;按照一下步骤即可完成redis数据的转移 1.进入redis客户端 2.使用 bgsave命令进行数据的备份&#xff0c;此命令完成后会在你的redis安装目…

方正畅享全媒体新闻采编系统 screen.do SQL注入漏洞复现(附脚本)

0x01 产品描述: 方正畅享全媒体新闻生产系统是以内容资产为核心的智能化融合媒体业务平台,融合了报、网、端、微、自媒体分发平台等全渠道内容。该平台由协调指挥调度、数据资源聚合、融合生产、全渠道发布、智能传播分析、融合考核等多个平台组成,贯穿新闻生产策、采、编、…

Windows下安装Rabbit MQ

一、安装环境&#xff1a; 系统&#xff1a;windows11; 环境配置安装&#xff1a;otp_win64_25.3.2.14.exe&#xff08;erlang类库&#xff09;&#xff1b; 服务应用安装&#xff1a;rabbitmq-server-3.12.4.exe&#xff1b; 二、erlang环境&#xff1a; 1.执行…