Redis 缓存优化接口性能的核心在于减少数据库直接访问。针对缓存穿透,可采用布隆过滤器拦截不存在请求或缓存空值并设置短过期时间;针对缓存雪崩,应避免大量 Key 同时失效,通过设置随机过期时间、使用互斥锁控制并发重建缓存、或采用双层缓存策略。此外,热点 Key 可设置永不过期或通过定时任务更新,确保高并发下系统稳定。
redis 缓存穿透、缓存雪崩、热点 Key 问题分析及解决方案
缓存穿透 缓存系统,按照 KEY 去查询 VALUE,当 KEY 对应的 VALUE 一定不存在的时候并对 KEY 并发请求量很大的时候,就会对后端造成很大的压力。查询一个必然不存在的数据。比如文章表,查询一个不存在的 id,每次都会访问 DB,如果有人恶意破坏,很可能直接对 DB 造成影响。由于缓存不命中,每次都要查询持久层 (回源),从而失去缓存的意义。解决方法 缓存层缓存空值 缓存太多空值,占用更多空间。(优化:给个空值过期时间) 存储层更新代码了,缓存层还是空值。(优化:后台设置时主动删除空值,并缓存把值进去) 将数据库中所有的查询条件,放到 布隆过滤器 中。当一个查询请求来临的时候,先经过布隆过滤器进行检查,如果请求存在这个条件中,那么继续执行,如果不在,直接丢弃。注意事项: 使用布隆过滤器时,如果数据库中有 10000 个条件,那么布隆过滤器的容量 size 设置的要稍微比 10000 大一些,比如 12000。 对于误判率的设置,根据实际项目,以及硬件设施来具体决定。但是一定不能设置为 0,并且误判率设置的越小,哈希函数跟数组长度都会更多跟更长,那么对硬件,内存中间的要求就会相应的高。 综上:我们可以利用布隆过滤器,将 redis 缓存击穿控制在一个可容忍的范围内。 缓存雪崩 (缓存失效) 如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。缓存层宕掉后,流量会像奔逃的野牛一样,打向后端存储。解决办法 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待; 可以通过缓存 reload 机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存; 不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀; 做二级缓存,或者双缓存策略:A1 为原始缓存,A2 为拷贝缓存; A1 失效时,可以访问 A2,A1 缓存失效时间设置为短期,A2 设置为长期。
SpringBoot 中如何解决 Redis 的缓存穿透、缓存击穿、缓存雪崩?
在使用 Redis 缓存时,可能会遇到一些缓存问题,最常见的包括缓存穿透、缓存击穿和缓存雪崩。1. 缓存穿透 缓存穿透指的是在缓存中没有找到需要的值,每次请求都会访问数据库,而由于数据库中也不存在需要的数据,导致每次请求返回的结果都为空,从而浪费了大量的服务端资源。这种情况可以通过添加布隆过滤器 (BloomFilter) 进行处理,将所有可能的查询参数哈希后存储起来,每次查询前先判断哈希值是否存在于布隆过滤器中,若不在则直接返回空结果。2. 缓存击穿 缓存击穿指的是一个原本存在的 key,在缓存失效的一刹那,同时有大量的并发请求过来,这些请求发现缓存中不存在该 key,于是就直接请求了数据库,从而导致了数据库瞬时压力过大甚至宕机的情况。这种情况可以通过为热点数据设置永不过期的方式解决,一般会使用 Redis 的 setnx(SET if Not eXists) 命令,将缓存数据永久保存在 Redis 中。3. 缓存雪崩 缓存雪崩指的是缓存中大量的 key,在同一时刻失效,导致大量的请求直接打到了数据库,从而导致数据库瞬时压力过大甚至宕机的情况。这种情况可以通过加入一个随机过期时间解决,不同的 key 分别设置不同的过期时间来保证不会在同一时间失效。也可以使用 Redis Cluster 技术对 Redis 数据库进行集群化部署,避免单点故障。
Redis 详解 (十二)------ 缓存穿透、缓存击穿、缓存雪崩
1、缓存穿透 一、概念 缓存穿透:缓存和数据库中都没有的数据,可用户还是源源不断的发起请求,导致每次请求都会到数据库,从而压垮数据库。如下图红色的流程:比如客户查询一个根本不存在的东西,首先从 Redis 中查不到,然后会去数据库中查询,数据库中也查询不到,那么就不会将数据放入到缓存中,后面如果还有类似源源不断的请求,最后都会压到数据库来处理,从而给数据库造成巨大的压力。二、解决办法 ①、业务层校验 用户发过来的请求,根据请求参数进行校验,对于明显错误的参数,直接拦截返回。比如,请求参数为主键自增 id,那么对于请求小于 0 的 id 参数,明显不符合,可以直接返回错误请求。②、不存在数据设置短过期时间 对于某个查询为空的数据,可以将这个空结果进行 Redis 缓存,但是设置很短的过期时间,比如 30s,可以根据实际业务设定。注意一定不要影响正常业务。③、布隆过滤器 关于布隆过滤器,后面会详细介绍。布隆过滤器是一种数据结构,利用极小的内存,可以判断大量的数据“一定不存在或者可能存在”。对于缓存击穿,我们可以将查询的数据条件都哈希到一个足够大的布隆过滤器中,用户发送的请求会先被布隆过滤器拦截,一定不存在的数据就直接拦截返回了,从而避免下一步对数据库的压力。2、缓存击穿 一、概念 缓存击穿:Redis 中一个热点 key 在失效的同时,大量的请求过来,从而会全部到达数据库,压垮数据库。这里要注意的是这是某一个热点 key 过期失效,和后面介绍缓存雪崩是有区别的。
Redis 使用 | 缓存穿透,雪崩,击穿以及解决方案分析
一。什么是 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能 DB 就挂掉了,要是有人利用不存在的 key 频繁攻击我们的应用,这就是漏洞。小点的单机系统,基本上用 postman 就能搞死,比如我自己买的阿里云服务 像这种你如果不对参数做校验,数据库 id 都是大于 0 的,我一直用小于 0 的参数去请求你,每次都能绕开 Redis 直接打到数据库,数据库也查不到,每次都这样,并发高点就容易崩掉了。缓存穿透解决方案 有很多种方法可以有效地解决缓存穿透问题。1.最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被 这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力。2.另外也有一个更为简单粗暴的方法 (我们采用的就是这种),如果一个查询返回的数据为空 (不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。二。什么是 缓存雪崩 我了解的,目前电商首页以及热点数据都会去做缓存,一般缓存都是定时任务去刷新,或者是查不到之后去更新的,定时任务刷新就有一个问题。举个简单的例子:如果所有首页的 Key 失效时间都是 12 小时,中午 12 点刷新的,我零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的 Key 都失效了。此时 1 秒 6000 个请求全部落数据库,数据库必然扛不住,它会报一下警,真实情况可能 DBA 都没反应过来就直接挂了。
FAQ
什么是缓存穿透?
缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
如何防止缓存雪崩?
可以通过加入一个随机过期时间解决,不同的 key 分别设置不同的过期时间来保证不会在同一时间失效。也可以使用 Redis Cluster 技术对 Redis 数据库进行集群化部署,避免单点故障。