缓存相关问题:雪崩、穿透、预热、更新、降级的深度解析

embedded/2024/11/15 4:04:01/

✨✨祝屏幕前的小伙伴们每天都有好运相伴左右✨✨
🎈🎈作者主页: 喔的嘛呀🎈🎈

目录

1. 缓存雪崩

1.1 问题描述

1.2 解决方案

1.2.1 加锁防止并发重建缓存

2. 缓存穿透

2.1 问题描述

2.2 解决方案

2.2.1 布隆过滤器防止无效请求

3. 缓存预热

3.1 问题描述

3.2 分析与解决方案

3.2.1 定时任务预热缓存

4. 缓存更新

4.1 问题描述

4.2 分析与解决方案

4.2.1 主动更新缓存

5. 缓存降级

5.1 问题描述

5.2 分析与解决方案

5.2.1 降级机制提供默认值

总结


在系统开发中,缓存是提升性能和降低数据库负载的重要手段。然而,缓存并非没有问题,常见的问题包括缓存雪崩、缓存穿透、缓存预热、缓存更新和缓存降级等。本文将详细分析这些缓存相关的问题,并提供解决方案。

1. 缓存雪崩

1.1 问题描述

       缓存雪崩是指在缓存中的大量数据同时过期或失效,导致大量请求直接落到数据库,压力剧增,可能导致系统崩溃。我们可以简单的理解为:由于原有缓存失效,新缓存未到期间 (例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

1.2 解决方案

1.2.1 加锁防止并发重建缓存

public class CacheService {private final Object lock = new Object();public Object getData(String key) {Object data = getFromCache(key);if (data == null) {synchronized (lock) {data = getFromCache(key);if (data == null) {data = getFromDatabase(key);putIntoCache(key, data);}}}return data;}// 其他业务逻辑...
}

2. 缓存穿透

2.1 问题描述

        缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。

2.2 解决方案

2.2.1 布隆过滤器防止无效请求

public class CacheService {private final BloomFilter<String> bloomFilter = new BloomFilter<>();public Object getData(String key) {if (!bloomFilter.mightContain(key)) {return null;}Object data = getFromCache(key);if (data == null) {data = getFromDatabase(key);putIntoCache(key, data);}return data;}// 其他业务逻辑...
}

3. 缓存预热

3.1 问题描述

      缓存预热是指在系统上线或重启后,将部分或全部数据预先加载到缓存中,防止大量请求直接访问数据库。

3.2 分析与解决方案

3.2.1 定时任务预热缓存

通过定时任务,在系统启动或每天凌晨1点等时机,将需要预热的数据加载到缓存中:

@Component
public class CacheWarmUpTask {@Autowiredprivate CacheService cacheService;@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行public void warmUpCache() {List<String> keysToWarmUp = getKeysToWarmUp();for (String key : keysToWarmUp) {cacheService.getData(key);}}private List<String> getKeysToWarmUp() {// 根据业务逻辑获取需要预热的缓存键列表// ...}
}

4. 缓存更新

4.1 问题描述

缓存更新是指数据库中的数据更新后,及时将缓存中的数据进行同步。

4.2 分析与解决方案

4.2.1 主动更新缓存

        除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种: (1)定时去清理过期的缓存; (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。 两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,大家可以根据自己的应用场景来权衡。

public class CacheService {public void updateCache(String key, Object newData) {// 更新缓存putIntoCache(key, newData);}// 其他业务逻辑...
}

5. 缓存降级

5.1 问题描述

       缓存降级是指在系统遇到异常或缓存失效的情况下,通过某种方式提供默认值或兜底数据,保证系统正常运行。

       当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。 降级的最终目的是保证核心服务可用,即使是有损的而且有些服务是无法降级的(如加入购物车、结算)。 以参考日志级别设置预案: (1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级; (2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警; (3)错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级; (4)严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。服务降级的目的,是为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要的缓存数据,可以采取服务降级策略,例如一个比较常见的做法就是Redis出现问题,不去数据库查询,而是直接返回默认值给用户。

5.2 分析与解决方案

5.2.1 降级机制提供默认值

缓存失效或异常时,提供默认值或兜底数据,确保系统正常运行:

public class CacheService {public Object getData(String key) {Object data = getFromCache(key);if (data == null) {data = getFromDatabase(key);if (data != null) {putIntoCache(key, data);} else {data = getDefaultData();}}return data;}private Object getDefaultData() {// 提供默认值或兜底数据// ...}// 其他业务逻辑...
}

总结

       通过深入分析缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题,并提供相应的解决方案,可以有效提高系统的稳定性和性能。在实际应用中,应根据业务场景选择合适的方案,综合考虑多方面因素,以保障系统的高可用性和稳定性。长文分析力求全面,希望能为读者提供深度的理解和实践指导。


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

相关文章

Laravel 6 - 第十一章 中间件

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

感觉眩晕就以为高血压犯了?如果伴有耳鸣,请警惕这种疾病

高血压被称为“无形杀手”&#xff0c;我国调查研究显示每3位成年人中就有1位高血压患者&#xff0c;典型表现为头痛、心悸耳鸣等&#xff0c;偶尔也存在阵发性眩晕等不典型表现。当出现耳鸣、眩晕等症状时切忌想当然以为是高血压&#xff0c;尤其是耳鸣和眩晕两者同时出现而且…

Windows如何安装spark

Apache Spark是一个开源的大数据处理框架&#xff0c;旨在提供高效、通用和易用的大数据处理引擎。它最初由加州大学伯克利分校AMPLab开发&#xff0c;并于2010年开源。 Spark提供了一个基于内存的计算引擎&#xff0c;可以在大规模数据集上执行高速的数据处理任务。相比传统的…

MySQL B+索引的工作原理及应用

引言 在数据库系统中&#xff0c;索引是优化查询、提高性能的关键技术之一。特别是在MySQL数据库中&#xff0c;B树索引作为最常用的索引类型&#xff0c;对数据库性能有着至关重要的影响。本文旨简单解析MySQL中B树索引的工作原理&#xff0c;帮助学生朋友们更好地理解和利用…

windows驱动开发-I/O请求(一)

I/O请求是内核中非常重要的部分&#xff0c;所有的驱动功能都使用I/O请求来交互&#xff0c;故理解了I/O请求也就理解了驱动的工作原理。 DeviceIoControl 这个函数主要就是用于发送I/O请求: BOOL DeviceIoControl (HANDLE hDevice, // CreateFile返回的设备句柄…

ShardingSphere 5.x 系列【25】 数据分片原理之 SQL 解析

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 分片执行流程1.1 Simple Push Down1.2 SQL Federation2. SQL 解析2.1 解析…

商城数据库88张表结构(十二)

DDL 45.商城信息表 CREATE TABLE wang_messages (id int(11) NOT NULL AUTO_INCREMENT COMMENT 自增id,msgType tinyint(4) NOT NULL DEFAULT 0 COMMENT 消息类型(0:后台手工发送的消息 1:系统自动发的消息),sendUserid int(11) NOT NULL DEFAULT 0 COMMENT 发送者id,receiveU…

html+css基础教程入门学习之DIV常用属性大全自己整理

实线 设置div的高度与文字的行高一样就可以了,即 line-height 和 height 的数值是一样的就可以了,最后给div一个 over-flow: hidden ,让超出的部分隐藏. **二、常用属性** 复制代码 代码如下: 1、Height:设置DIV的高度&#xff1b;Width:设置DIV的宽度。 2、margin:用于设…