缓存常见问题:缓存穿透、雪崩、击穿及解决方案分析

devtools/2024/10/22 16:53:29/

1. 什么是缓存穿透,怎么解决?

        缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请求该数据都要去数据库中查询一遍。如果有恶意攻击者不断请求系统中不存在的数据,会导致短时间大量请求落在数据库上,造成数据库压力过大,甚至导致数据库承受不住而宕机崩溃。

        缓存穿透的关键在于在Redis中查不到key值,它和缓存击穿的根本区别在于传进来的key在Redis中是不存在的。假如有黑客传进大量的不存在的key,那么大量的请求打在数据库上是很致命的问题,所以在日常开发中要对参数做好校验,一些非法的参数,不可能存在的key就直接返回错误提示。

正常的查询流程

缓存穿透查询流程

解决方法:

方案一:缓存空数据

  • 将无效的key存放进Redis中:

当出现Redis查不到数据,数据库也查不到数据的情况,也将其缓存起来,但设置一个较短的过期时间,这样即使后续的恶意请求再次访问相同的键,也能够从缓存中获取结果,减轻数据库压力。但这种处理方式是有问题的,假如传进来的这个不存在的Key值每次都是随机的,那存进Redis也没有意义。

优点:实现简单

缺点:消耗内存,可能会发生数据不一致的问题。

方案二:布隆过滤器

  • 使用布隆过滤器:

        在缓存之前再加一个布隆过滤器,将数据库中的所有key都存储在布隆过滤器中,在查询Redis前先去布隆过滤器查询 key 是否存在,如果不存在就直接返回,不让其访问数据库,从而避免了对底层存储系统的查询压力。

  • 布隆过滤器的设计实现原理

        如果数据比较少,可以把数据库中的数据全部放到内存的一个map中。这样能够非常快速的识别,数据在缓存中是否存在。如果存在,则让其访问缓存。如果不存在,则直接拒绝该请求。但如果数据量太大,全都放到内存中,会占用太多的内存空间。因此要使用布隆过滤器。

        布隆过滤器的底层使用bit数组存储数据,该数组中的元素默认值为0。布隆过滤器第一次初始化的时候,会把数据库中所有已存在的key,经过一些列的hash算法(比如:三次hash算法)计算,每个key都会计算出多个位置,然后把这些位置上的元素值设置成1。之后,有用户key请求过来的时候,再用相同的hash算法计算位置。

  • 如果多个位置中的元素值都是1,则说明该key在数据库中已存在。这时允许继续往后面操作。
  • 如果有1个以上的位置上的元素值是0,则说明该key在数据库中不存在。这时可以拒绝该请求,而直接返回。

        但若布隆过滤器中存储的数据量过大,会出现误判的情况,即:原本这个key在数据库中是不存在的,但布隆过滤器确认为存在。同时如果数据库中的数据更新了,需要同步更新布隆过滤器。但它跟数据库是两个数据源,就可能存在数据不一致的情况。因此需要及时同步更新修改的内容。

误判率:数组越小误判率就越大,数组越大误判率就越小,但是同时带来了更多的内存消耗。

优点:内存占用较少,没有多余key

缺点:实现复杂,存在误判

        如何选择:针对一些恶意攻击,攻击带过来的大量key是随机,那么我们采用第一种方案就会缓存大量不存在key的数据。那么这种方案就不合适了,我们可以先对使用布隆过滤器方案进行过滤掉这些key。所以,针对这种key异常多、请求重复率比较低的数据,优先使用第二种方案直接过滤掉。而对于空数据的key有限的,重复率比较高的,则可优先采用第一种方式进行缓存

2. 缓存雪崩及解决方案

        缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

解决方案:

方案一:均匀过期

        设置不同的过期时间,让缓存失效的时间尽量均匀,避免相同的过期时间导致缓存雪崩,造成大量数据库的访问。如把每个Key的失效时间都加个随机值,setRedis(Key,value,time + Math.random() * 10000);,保证数据不会在同一时间大面积失效。

方案二:构建缓存高可用集群(针对缓存服务故障情况)

方案三:服务熔断、限流、降级等措施保障。

3. 缓存击穿及解决方案

        缓存击穿跟缓存雪崩有点类似,缓存雪崩是大规模的key失效,而缓存击穿是某个热点的key失效,大并发集中对其进行请求,就会造成大量请求读缓存没读到数据,从而导致高并发访问数据库,引起数据库压力剧增。这种现象就叫做缓存击穿。

解决方案:

方案一:互斥锁

  • 缓存失效后,通过互斥锁或者队列来控制读数据写缓存的线程数量,比如某个key只允许一个线程查询数据和写缓存,其他线程等待。这种方式会阻塞其他的线程,此时系统的吞吐量会下降。单机通过synchronized或lock来处理,分布式环境采用分布式锁。

        原理:线程1在查询缓存发现未命中的情况下,获取互斥锁,然后查询数据库重建缓存数据,写入缓存后,释放互斥锁。在线程1重建数据的时候,线程2也未命中缓存想重建时,在获取互斥锁时会失败,只能休眠一会儿再次尝试,直至线程1完成重建缓存的流程释放互斥锁后,线程2再查询缓存并命中。

优点:强一致性(适用于严格要求缓存一致性的场景)

缺点:性能差

方案二

  • 热点数据缓存永远不过期。永不过期实际包含两层意思:
    • 物理不过期,针对热点key不设置过期时间
    • 逻辑过期,把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建。

        原理:线程1在查询缓存发现逻辑时间快过期时,获取互斥锁,然后后台开启一个新的线程,查询数据库重建缓存数据,写入缓存,重置逻辑过期时间,再释放锁。当线程2在查询缓存也发现逻辑时间快过期时,获取互斥锁失败,此时直接从缓存中返回过期的数据。

        优点:可用性高,性能高

        缺点:存在数据不一致的情况(适用于不严格要求缓存一致性的场景)


http://www.ppmy.cn/devtools/127891.html

相关文章

【机器学习算法】基于python天气预测数据分析可视化系统(完整系统源码+数据库+开发笔记+详细部署教程)✅

文章目录 【机器学习算法】基于python天气预测数据分析可视化系统(完整系统源码数据库开发笔记详细部署教程)✅ 一、项目背景 二、研究目的 三、项目意义 四、项目功能 五、项目创新点 六、开发技术介绍 七、数据库设计 八、算法介绍 九、项目…

通过华为鲲鹏认证发行上市的集成平台产品推荐

华为鲲鹏认证是技术实力与品质的权威象征,代表着产品达到了高标准的要求。从技术层面看,认证确保产品与华为鲲鹏架构深度融合,能充分释放鲲鹏芯片的高性能、低功耗优势,为集成平台的高效运行提供强大动力。在安全方面,…

如何实现安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯

在工业自动化中,实现不同品牌、不同型号设备之间的通讯是确保生产流程顺畅、高效运行的关键。本文详细介绍了安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯的具体方法。 一.软硬件需求 1.一台安川MP3300CPU301,其IP地址是192.…

【贪心算法】(第二篇)

目录 最⼤数(medium) 题目解析 讲解算法原理 编写代码 摆动序列(medium) 题目解析 讲解算法原理 编写代码 最⼤数(medium) 题目解析 1.题目链接:. - 力扣(LeetCode&#xf…

leetcode动态规划(八)-不同的二叉搜索树

题目 96.不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n 3 输出:5示例 2: 输入&#xff…

Redis --- 第四讲 --- 常用数据结构 --- Hash、List

一、Hash哈希类型的基本介绍。 哈希表:之前学过的所有数据结构中,最最重要的。 1、日常开发中,出场频率非常高。 2、面试中,非常重要的考点。 Redis自身已经是键值对结构了。Redis自身的键值对就是通过哈希的方式来组织的。把…

探索 SVG 创作新维度:svgwrite 库揭秘

文章目录 **探索 SVG 创作新维度:svgwrite 库揭秘**背景介绍库简介安装指南基础函数使用实战场景常见问题与解决方案总结 探索 SVG 创作新维度:svgwrite 库揭秘 背景介绍 在数字艺术和网页设计领域,SVG(Scalable Vector Graphic…

智能听诊器:宠物健康数据的守护者

智能听诊器的出现,为宠物健康数据的管理提供了新的解决方案。它能够收集宠物的生理数据,并将其安全地存储在云端,这样即使宠物主人更换设备或遗失数据,也能轻松恢复宠物的健康记录。这种数据的长期保存和备份,对于宠物…