“缓存穿透”、“缓存击穿”和“缓存雪崩”的概念和解决办法

马谦马谦马谦 编程语言评论405字数 891阅读2分58秒阅读模式

一、缓存

缓存的作用一般是为了减轻数据库压力设计的,因为数据都是读写磁盘,当并发量大的时候,磁盘IO可能跟不上并发量。而缓存一般设计都是放在内存中的,最常见的例如redis和memcached,都是把数据都缓存在内存中。读写内存的速度比磁盘快很多,因此把常用的数据都放到内存中做缓存可以给数据库减轻很大的压力。

一个正常的缓存处理流程为:

  1. 先判断缓存中是否存在数据,如果缓存存在数据,直接读缓存中的数据。
  2. 如果缓存不存在,从数据库读数据。
  3. 如果数据库中存在数据,返回数据库中的数据并写到缓存。
  4. 如果数据库中也不存在数据,直接返回。

“缓存穿透”、“缓存击穿”和“缓存雪崩”的概念和解决办法

而作为缓存系统,需要考虑的几个问题是:缓存穿透、缓存击穿和缓存雪崩。

二、缓存穿透

缓存穿透:查询一个数据库不存在的数据,因为数据都不存在,所以缓存中也不存在,请求会直接去数据库中查询,这种情况就产生了缓存穿透。

例如对一个只含非负整数的表中查询id = -1的记录,缓存中不存在数据,所以每次都会请求数据库。当有攻击者恶意使用这种方式频繁请求数据时,会给后端数据库造成极大的压力。

解决方案:

  1. 增加数据校验,直接过滤掉明显不存在的数据。这里一般采用布隆过滤器,预先生成所有可能的数据的bitmap,请求数据库前先在过滤器中查找,过滤掉不可能的数据。
  2. 对不存在的值也设置缓存,在数据库中查询到不存在的数据之后在缓存中添加一个key=null的值。

三、缓存击穿

缓存击穿:某个key缓存在某一时刻失效,由于请求量特别大,导致这一时刻的所有请求同时都直接请求数据库,给数据库带来巨大压力。

解决方案:使用互斥锁或者其它方法锁住这个key(单例模式),当有请求已经在查询这个key时,等待请求,这个请求完成后数据写入缓存再从缓存中读取数据。

四、缓存雪崩

缓存雪崩:给一些键值设置了过期时间,同一时刻这些数据同时失效,请求直接到达数据库。

解决方案:

  1. 和缓存击穿一样,使请求单例执行。
  2. 不要给缓存的过期时间都设置成一样的,设置超时事件的时候加上一个随机时间作为时间。

缓存雪崩和缓存击穿其实一样,缓存击穿时缓存雪崩的一个特例。

两者的区别:缓存雪崩是指多个缓存数据同时失效,而缓存击穿特指某一个数据失效。

 最后更新:2020-2-1
马谦马谦马谦
  • 本文由 马谦马谦马谦 发表于 2019年9月15日11:19:07
  • 转载请务必保留本文链接:https://www.dyxmq.cn/program/code/concepts-and-solutions-for-cache-penetration-cache-breakdown-and-cache-avalanche.html
解决gvm工具无法下载安装包的问题 Golang

解决gvm工具无法下载安装包的问题

GVM(Go Version Manager)是一款用于管理和切换不同Go语言版本的工具。它允许用户在同一台计算机上轻松安装、使用和管理多个Go版本,同时还能确保项目之间的依赖关系井然有序。GVM的主...
goland配置proto文件搜索路径 Golang

goland配置proto文件搜索路径

默认情况下,goland(jetbrains家的软件:idea、pycharm、phpstorm以及webstorm都是一样)安装protobuf插件后只会在一个特定的库路径下搜索proto文件。如果...
C++文件输入输出流fstream的基本用法 C/C++

C++文件输入输出流fstream的基本用法

一、文件流 C++的IO类中定义了三个文件读写流fstream、ifstream以及ofstream,它们都继承于相同的父类istream,通过不同的实现以实现不同的文件流操作。 三者的区别为: if...
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证