缓存系统的三大挑战:缓存击穿、缓存穿透和缓存雪崩

news2024/10/8 17:43:54

文章目录

  • 背景
  • 一、缓存击穿
    • 1. 定义
    • 2. 场景
    • 3. 影响
    • 4. 解决方案
  • 二、缓存穿透
    • 1. 定义
    • 2. 场景
    • 3. 影响
    • 4. 解决方案
  • 三、缓存雪崩
    • 1. 定义
    • 2. 场景
    • 3. 影响
    • 4. 解决方案
  • 总结

背景

在现代互联网应用中,缓存是提高系统性能和响应速度的重要手段之一,它扮演着至关重要的角色。缓存能够显著提升系统的性能和响应速度,减轻数据库等后端存储的压力。然而,缓存系统也并非无懈可击,如果缓存使用不当,可能导致系统故障或性能下降,其中较为典型的就是缓存击穿、缓存穿透和缓存雪崩。接下来,我们将详细探讨这三个概念,并提供相应的解决方案。

一、缓存击穿

1. 定义

缓存击穿是指一个非常热门的数据(通常是热点数据)在缓存中过期或被删除后,同时有大量的请求并发访问该数据。由于缓存中数据已过期,这些请求会直接穿透到数据库,对数据库造成瞬间的巨大压力。

2. 场景

例如,在一个电商系统中,某一款热门商品的详细信息在缓存中设置了较短的过期时间(比如 10 分钟)。当该商品的缓存过期时,恰好正值电商大促(购物高峰期),大量用户同时点击查看该商品详情,此时这些请求就会直接访问数据库来获取数据,可能导致数据库的负载急剧升高,甚至可能出现短暂的卡顿或无法响应的情况。

3. 影响

数据库可能因为突然的高并发访问而变得不可用,导致系统性能急剧下降甚至崩溃。

4. 解决方案

  • 设置合理的过期时间:避免所有缓存同时过期,可以采用随机过期时间或者设置不同的过期时间。
  • 互斥锁机制:在缓存失效时,使用互斥锁(如Redis的分布式锁)确保只有一个线程能够访问数据库并重新加载缓存,其他线程等待缓存加载完成后再从缓存中读取数据。Java 可以使用 synchronized 关键字或者 ReentrantLock 等锁机制来实现。
String lockKey = "lock:cache:key";
if (redisTemplate.opsForValue().setIfAbsent(lockKey, "true", 10, TimeUnit.SECONDS)) {
    try {
        // 从数据库中获取数据
        Object data = dbService.getData(key);
        // 将数据写入缓存
        redisTemplate.opsForValue().set(key, data, 600, TimeUnit.SECONDS);
    } finally {
        // 释放锁
        redisTemplate.delete(lockKey);
    }
} else {
    // 等待一段时间后重试
    Thread.sleep(50);
    getDataFromCache(key);
}
  • 永不过期:对于一些特别热点且更新不频繁的数据,可以考虑将其设置为永不过期,或者在后台定时更新缓存。注意保证数据的一致性。

二、缓存穿透

1. 定义

缓存穿透是指查询一个不存在的数据,由于缓存中没有该数据,每次请求都会穿透缓存直接访问数据库,而数据库中也没有该数据。这种情况会导致大量的无效请求直接打到数据库上,增加了数据库的压力。

2. 场景

恶意攻击者故意发送大量不存在的用户ID进行查询。或者由于业务逻辑错误,前端传递了错误的参数,导致查询的数据在数据库中不存在。

3. 影响

数据库会因为处理大量无效请求而消耗资源,还可能影响正常请求的处理。

4. 解决方案

  • 缓存空值:当查询的数据在数据库中不存在时,将这个空值也缓存起来,并设置一个较短的过期时间。这样后续相同的请求可以直接从缓存中获取空值,减少对数据库的访问。注意在数据真正存在时,及时更新缓存。
  • 布隆过滤器(Bloom Filter):在缓存之前加一层布隆过滤器,预先判断数据是否存在。如果布隆过滤器判断数据不存在,则直接返回空结果,避免穿透到数据库。如果布隆过滤器判断数据可能存在,再去查询缓存和数据库。
    接口限流:对请求进行限流,防止恶意攻击导致的大量无效请求。

三、缓存雪崩

1. 定义

缓存雪崩是指在某一时刻,大量的缓存数据同时失效或被删除,导致大量请求全部穿透到数据库,从而对数据库造成巨大的访问压力,系统性能急剧下降,甚至可能导致系统崩溃。

2. 场景

  • 缓存服务器宕机:如果缓存系统(如Redis、Memcached等)发生故障或重启,所有缓存数据会瞬间失效,导致所有的请求都直接打到数据库上。
  • 大量缓存数据同时过期:如果设置了相同的过期时间,大量缓存数据会在同一时间点过期,导致这些数据的请求同时到达数据库。
  • 大规模数据更新:在某些情况下,可能需要批量更新缓存中的数据,如果处理不当,可能会导致大量缓存数据同时失效。

3. 影响

  • 数据库压力剧增:短时间内大量的请求直接访问数据库,可能导致数据库负载过高,响应变慢,甚至崩溃。
  • 系统性能下降:由于数据库无法及时处理这么多请求,系统的整体性能会显著下降,用户体验也会受到影响。
  • 服务不可用:在极端情况下,数据库可能完全无法处理请求,导致服务不可用。#

4. 解决方案

  • 分散过期时间:
    在设置缓存过期时间时,避免将大量数据的过期时间设置为同一时刻。可以采用一定的随机策略或者按照数据的访问频率等因素,为不同的数据设置不同的过期时间,使得缓存数据在一段时间内逐步过期,而不是集中在一个瞬间过期。例如,可以在原有过期时间的基础上加上一个随机的时间偏移量。
int baseExpireTime = 600; // 基础过期时间(秒)
int randomExpireTime = (int) (Math.random() * 60); // 随机数(0-60秒)
int finalExpireTime = baseExpireTime + randomExpireTime;
  • 互斥锁机制:
    在缓存失效时,使用互斥锁(如Redis的分布式锁)确保只有一个线程能够访问数据库并重新加载缓存,其他线程等待缓存加载完成后再从缓存中读取数据。
  • 多级缓存:构建多级缓存架构,除了应用本地缓存外,还可以使用分布式缓存(如 Redis)等。当一级缓存失效时,还可以从其他级别的缓存中获取数据,减轻对数据库的压力。并且,不同级别的缓存可以采用不同的过期策略和缓存更新机制,进一步提高缓存的可靠性和性能。
  • 缓存预热:
    在系统启动或低峰时段预先加载热点数据到缓存中,避免在高峰时段出现缓存大面积失效的情况。
  • 限流和降级:当缓存服务出现故障或者缓存大面积失效时,可以采取限流和缓存降级策略。即暂时停止访问缓存,直接从数据库获取数据,并对数据进行一些简单的处理后返回给用户。同时,在系统中记录缓存故障信息,以便后续进行排查和恢复。在缓存恢复正常后,再逐步恢复正常的缓存访问流程。

总结

缓存击穿、缓存穿透和缓存雪崩是缓存系统中常见的三个问题,它们分别描述了不同场景下的缓存失效情况及其对系统的影响。理解它们的概念和原理,并采取相应的解决方案,对于保障系统的性能、稳定性和可靠性具有重要意义。
实际的系统设计和开发中,需要综合考虑业务需求、数据特点和系统架构等因素,灵活运用各种技术手段来预防和应对这些问题,以确保缓存系统能够更好地为应用服务,提高系统的稳定性和性能,提升用户体验。
希望本文能帮助你更好地理解和应对这些缓存问题。

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

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

相关文章

reactNative本地调试localhost踩坑

本地调试请求localhost的时候 1.要和电脑处在同一局域网下面(同一个wifi) 2.把baseURL的localhost改成命令行中ipconfig查询到的IPv4 地址 . . . . . . . . . . . . : (例如)192.168.1.103 如果报错Net Work Error,可…

算法知识点————贪心

贪心:只考虑局部最优解,不考虑全部最优解。有时候得不到最优解。 DP:考虑全局最优解。DP的特点:无后效性(正在求解的时候不关心前面的解是怎么求的); 二者都是在求最优解的,都有最优…

如何扫描HTTP代理:步骤与注意事项

HTTP代理是一个复杂的过程,通常用于寻找可用的代理服务器,以便在网络中实现匿名或加速访问。虽然这个过程可以帮助用户找到适合的代理,但也需要注意合法性和道德问题。本文将介绍如何扫描HTTP代理,并提供一些建议和注意事项。 什…

剖析十大经典二叉树题目:C 语言代码实现与深度解读

💯前言 二叉树是数据结构中的重要概念,在算法和编程中有着广泛的应用。以下是十大经典的二叉树题目及其解析与 C 语言代码实现,同时也会说明题目来源。 二叉树的基本概念👉【剖析二叉树】 目录 💯二叉树的遍历 ⭐前…

AI大模型真的是大龄程序员的新的出路吗?_大龄程序员ai创业

前言 在IT行业的高速运转中,许多资深程序员到了一定年龄后,会发现自己陷入了职业发展的瓶颈。尤其是在北京这样的大厂,业务波动、部门调整以及裁员风险,都让“40”的程序员们感受到了前所未有的压力。当昔日的技术热情逐渐消退&a…

在C#中使用适配器Adapter模式和扩展方法解决面向对象设计问题

之前有阵子在业余时间拓展自己的一个游戏框架,结果在实现的过程中发现一个设计问题。这个游戏框架基于MonoGame实现,在MonoGame中,所有的材质渲染(Texture Rendering)都是通过SpriteBatch类来完成的。举个例子&#xf…

新书速览|你好,C++

《你好,C》 本书内容 《你好,C》主要介绍C开发环境的搭建、基础语法知识、面向对象编程思想以及标准模板库的应用,特别针对初学者在学习C过程中可能遇到的难点提供了解决方案。全书共分13章,以一个工资程序的不断优化和完善为线索…

ChatGPT助力文献综述写作:提升效率与写作技巧!

文献综述在论文写作中占有举足轻重的地位。它不仅帮助我们梳理已有的研究成果,还能为自己的研究奠定基础。许多同学在撰写文献综述时常常感到头疼:如何处理海量的信息?如何将不同的观点有条理地整合起来?再加上学术语言的高要求&a…

定时任务。

引入 1.启动类上加上注解 2.新建一个定时任务的管理类,交给Spring管理 案例 案例1:fixedRate //上次任务开始到下次任务开始的时间间隔为5秒 //每隔5秒执行一次,不需要等上个任务执行完 Scheduled(fixedRate 5000) public void mask01() throws Inte…

python:web自动化工具selenium安装和配置(1)

UI自动化测试 UI自动化测试(User Interface Automation Testing)是一种通过编写脚本或使用自动化测试工具,对界面(UI)进行自动化测试的方法。原理主要是模拟用户打开客户端或网页的UI界面,自动化执行用户界…

【Java 问题】基础——泛型

接上文 泛型 47.Java 泛型了解么?什么是类型擦除?介绍一下常用的通配符? 47.Java 泛型了解么?什么是类型擦除?介绍一下常用的通配符? 什么是泛型? Java 泛型(generics)是…

REINFORCEMENT LEARNING THROUGH ACTIVE INFERENCE

摘要 强化学习(RL)的核心原则是智能体寻求最大化累积奖励之和。相比之下,主动推理,认知和计算神经科学中的一个新兴框架,提出代理人采取行动,以最大限度地提高有偏见的生成模型的证据。在这里,…

上门安装维修系统小程序开发详解及源码示例

随着智能家居和设备的普及,消费者对上门安装和维修服务的需求日益增加。为了满足这一市场需求,开发一款上门安装维修系统小程序成为了一种有效的解决方案。本文将详细介绍上门安装维修系统小程序的开发过程,并提供一个简单的源码示例&#xf…

人工智能的未来

引言 人工智能的未来发展将是科技与人类社会深度融合的过程。随着技术的不断进步,AI将在全球经济、文化、政治及道德伦理等领域产生深远影响。本文将探讨人工智能在未来可能的技术进步、应用领域、社会影响、伦理挑战,以及对全球未来的展望。 一、技术前…

数据结构之——二叉树

一、二叉树的基本概念 二叉树是数据结构中的重要概念,每个节点最多有两个子树,分别为左子树和右子树。这种结构具有明确的层次性和特定的性质。 二叉树有五种基本形态: 空二叉树:没有任何节点。只有一个根结点的二叉树&#xff…

【HTTPS】深入解析 https

我的主页:2的n次方_ 1. 背景介绍 在使用 http 协议的时候是不安全的,可能会出现运营商劫持等安全问题,运营商通过劫持 http 流量,篡改返回的网页内容,例如广告业务,可能会通过 Referer 字段 来统计是…

kubernetes get pods的STATUS字段显示ImagePullBackOff 的解决办法

问题: [rootmaster ingress]# kubectl -n ingress-nginx get pods NAME READY STATUS RESTARTS AGE ingress-nginx-admission-create-mcrc6 0/1 ImagePullBackOff 0 37m ingress-…

掌握RocketMQ——基本概念和系统架构

简述RcoketMQ 概念:RocketMQ是一个开源的分布式消息中间件,由阿里巴巴开发并贡献给Apache软件基金会。它用于处理高吞吐量、低延迟的消息传递,并广泛应用于现代分布式系统中。 1 基本概念 1.1 消息 (Message) 概念:消息是信息传…

自定义协议以及序列化和反序列化

我们知道TCP是全双工的,可以同时进行发收,因为他有一个发送缓冲区和一个接收缓冲区 我们使用write其实是把数据拷贝到发送缓冲区,使用read接收缓冲区的数据,其实是把数据拷贝到文件缓冲区里,发送的过程中,我…

脸书(Facebook)高效开发国外客户的6个技巧

Facebook作为全球使用人数最多的社媒平台,全球三分之一的人都在用。做外贸的话基本上是必须要去掌握的一个平台,因为通过Facebook是可以开发到很多其他渠道平时开发不到的优质客户的。 Facebook跟LinkedIn不同,LinkedIn比较偏向于大B的客户&…