文档章节

redis缓存击穿、缓存穿透、缓存雪崩

noob_fly
 noob_fly
发布于 02/19 22:10
字数 1263
阅读 80
收藏 13

对于缓存而言,

  1. 约束好key的规范,合理确定Val值的大小,来选择缓存的介质(相应的根据实际的业务情况分析,哪种缓存方式合适 redis、zk、memcached 亦或者 local)。(生产实际案例:redis做缓存,因Val值过大的key太多,导致reids的性能出现了问题,造成业务不可用
  2. 合理分配缓存失效时间(缓存是物理有失效时间 ? 亦或者 在缓存的对象里增加一个虚拟的失效时间,而物理上是没有过期时长的)
  3. 缓存没值,是继续轮询获取呢? 还是暂缓本次获取(retry 次数和超时时间)?还是竞争锁去查db呢。
  4. 合理加锁控制分布式单线程DB查询写缓存操作

缓存穿透

程序在处理缓存时,一般是先从缓存查询,如果缓存没有这个key获取为null,则会从DB中查询,并设置到缓存中去。

按这种做法,那查询一个一定不存在的数据值,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

解决办法

  1. 最好对于每一个缓存key都有一定的规范约束,这样在程序中对不符合parttern的key 的请求可以拒绝。(但一般key都是通过程序自动生成的)
  2. 将可能出现的缓存key的组合方式的所有数值以hash形式存储在一个很大的bitmap中<布隆过滤器>(需要考虑如何将这个可能出现的数据的hash值之后同步到bitmap中, eg. 后端每次新增一个可能的组合就同步一次),一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力
  3. 常用: 如果对应在数据库中的数据都不存在,我们将此key对应的value设置为一个默认的值,比如“NULL”,并设置一个缓存的失效时间。当然这个key的时效比正常的时效要小的多

有点类似于将一个key通过n个不同的hash函数定位成n个整数,然后将这n个整数定位在一个长度在M的初始数值为0的数组下标上,设置该n个下标的数值为1。 那只要当查询过来,用这n个hash函数定位判定都为1那基本就存在,只要有任一下标的数组值不是1,则代表不存在。

缓存雪崩

指的是大量缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。

解决办法

  1. 这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布,设置不同的过期时间。
  2. 用加分布式锁或者分布式队列的方式保证缓存的单线程(进程)写 (eg. redis的 SETNX,从而避免失效时大量的并发请求落到底层存储系统上。在加锁方法内先从缓存中再获取一次(防止另外的线程优先获取锁已经写入了缓存),没有再查DB写入缓存(当然也可以: 在没有获取锁(tryLock)的线程中一直轮询缓存,至超限时)

缓存击穿

指的是热点key在某个特殊的场景时间内恰好失效了,恰好有大量并发请求过来了,造成DB压力。

解决办法

与缓存雪崩的解决方法类似: 用加锁或者队列的方式保证缓存的单线程(进程)写,在加锁方法内先从缓存中再获取一次,没有再查DB写入缓存。 

还有一种比较好用的(针对缓存雪崩与缓存击穿):

物理上的缓存是不设置超时时间的(或者超时时间比较长), 但是在缓存的对象上增加一个属性来标识超时时间(此时间相对小)。 当获取到数据后,校验数据内部的标记时间,判定是否快超时了,如果是,异步发起一个线程(控制好并发)去主动更新该缓存。

这种方式会导致一定时间内,有些请求获取缓存会拿到过期的值,看业务是否能接受而定。

 

© 著作权归作者所有

共有 人打赏支持
noob_fly
粉丝 8
博文 101
码字总数 119913
作品 0
广州
程序员
私信 提问
缓存穿透、缓存击穿和缓存雪崩实践

我们使用缓存的主要目是提升查询速度和保护数据库等稀缺资源不被沾满。而缓存最常见的问题是缓存穿透、击穿和雪崩,在高并发下这三种情况都会有大量请求落到数据库,导致数据库资源沾满,引起...

xiaolyuh
2018/12/28
0
0
面对海量请求,缓存设计还应该考虑哪些问题?

  【IT168 技术】从第一个缓存框架 Memcached 诞生以来,缓存就广泛地存在于互联网应用中。如果你的应用流量很小,那么使用缓存可能并不需要做多余的考虑。但如果你的应用流量达到了成百上...

博客园
2018/05/23
0
0
面对海量请求,缓存设计还应该考虑哪些问题?

从第一个缓存框架 Memcached 诞生以来,缓存就广泛地存在于互联网应用中。如果你的应用流量很小,那么使用缓存可能并不需要做多余的考虑。但如果你的应用流量达到了成百上千万,那么你就不得...

陈树义
2018/05/15
0
0
ASP.NET Core 中的缓存

目录 缓存的基本概念 缓存原理 缓存设计 分布式缓存 Memcache 与 Redis 的比较 缓存穿透,缓存击穿,缓存雪崩解决方案 数据一致性 使用内置 MemoryCache 使用分布式缓存 Redis 使用 Stackexc...

RoyZShare
2018/08/14
0
0
缓存穿透,缓存雪崩的四种解决方案

前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑...

小致dad
2018/12/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Netty如何实现Reactor模式

在前面的文章中(Reactor模型详解),我们讲解了Reactor模式的各种演变形式,本文主要讲解的则是Netty是如何实现Reactor模式的。这里关于Netty实现的Reactor模式,需要说明的是,其实现的模式...

爱宝贝丶
6分钟前
0
0
前端面试:谈谈 JS 垃圾回收机制

摘要: 不是每个人都回答的出来... 原文:前端面试:谈谈 JS 垃圾回收机制 作者:前端小智 最近看到一些面试的回顾,不少有被面试官问到谈谈JS 垃圾回收机制,说实话,面试官会问这个问题,说...

Fundebug
7分钟前
0
0
修改django中的querydict

修改django中的querydict 在正常的请求/响应周期中访问时,request.POST和request.GET上的QueryDicts将是不可变的.要获得可变版本,您需要使用QueryDict.copy().或者,使用一个小技巧 # da...

_Change_
16分钟前
0
0
php简易缓存函数

不需要特别复杂的缓存的时候可以采用简易缓存,设置缓存有效期,有效返回数据,无效返回无效.然后每日清空一下所有缓存.毕竟缓存太多了也占地方 /** * 缓存 * @param $key 缓存名 * @p...

xiaogg
20分钟前
0
0
linux 使用文件增加虚拟内存 swap

之前买了个云服务器玩,不过是最低配置的1核1G,后来发现这个内存太小了,随便装几个软件就不行了,内存消耗较大的像 redis 运行起来很多问题。 这些时间了解了下 docker 容器,去尝试了下发...

非摩尔根
24分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部