Redis缓存雪崩、缓存穿透、热点Key解决方案和分析
缓存穿透
缓存系统,按照KEY去查询VALUE,当KEY对应的VALUE一定不存在的时候并对KEY并发请求量很大的时候,就会对后端造成很大的压力。
(查询一个必然不存在的数据。比如文章表,查询一个不存在的id,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成影响。)
由于缓存不命中,每次都要查询持久层。从而失去缓存的意义。
解决方法:
1、缓存层缓存空值。
–缓存太多空值,占用更多空间。(优化:给个空值过期时间)
–存储层更新代码了,缓存层还是空值。(优化:后台设置时主动删除空值,并缓存把值进去)
2、将数据库中所有的查询条件,放到布隆过滤器中。当一个查询请求来临的时候,先经过布隆过滤器进行检查,如果请求存在这个条件中,那么继续执行,如果不在,直接丢弃。
备注:
比如数据库中有10000个条件,那么布隆过滤器的容量size设置的要稍微比10000大一些,比如12000.
对于误判率的设置,根据实际项目,以及硬件设施来具体决定。但是一定不能设置为0,并且误判率设置的越小,哈希函数跟数组长度都会更多跟更长,那么对硬件,内存中间的要求就会相应的高。
private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.0001);
有了size跟误判率,那么布隆过滤器就会产生相应的哈希函数跟数组。
综上:我们可以利用布隆过滤器,将redis缓存击穿控制在一个可容忍的范围内。
缓存雪崩(缓存失效)
如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。
缓存层宕掉后,流量会像奔逃的野牛一样,打向后端存储
解决方法:
- 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
- 可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存
- 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
- 做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。
热点key
(1) 这个key是一个热点key(例如一个重要的新闻,一个热门的八卦新闻等等),所以这种key访问量可能非常大。
(2) 缓存的构建是需要一定时间的。(可能是一个复杂计算,例如复杂的sql、多次IO、多个依赖(各种接口)等等)
于是就会出现一个致命问题:在缓存失效的瞬间,有大量线程来构建缓存(见下图),造成后端负载加大,甚至可能会让系统崩溃 。
解决方法:
1. 使用互斥锁(mutex key):这种解决方案思路比较简单,就是只让一个线程构建缓存,其他线程等待构建缓存的线程执行完,重新从缓存获取数据就可以了
2. "提前"使用互斥锁(mutex key):在value内部设置1个超时值(timeout1), timeout1比实际的memcache timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache。然后再从数据库加载数据并设置到cache中。
3. "永远不过期":
这里的“永远不过期”包含两层意思:
(1) 从redis上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是“物理”不过期。
(2) 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期
4. 资源保护:可以做资源的隔离保护主线程池,如果把这个应用到缓存的构建也未尝不可。
四种方案对比:
作为一个并发量较大的互联网应用,我们的目标有3个:
1. 加快用户访问速度,提高用户体验。
2. 降低后端负载,保证系统平稳。
3. 保证数据“尽可能”及时更新(要不要完全一致,取决于业务,而不是技术。)
所以第二节中提到的四种方法,可以做如下比较,还是那就话:没有最好,只有最合适。
| 解决方案 | 优点 | 缺点 |
| 简单分布式锁(Tim yang) |
1. 思路简单 2. 保证一致性 |
1. 代码复杂度增大 2. 存在死锁的风险 3. 存在线程池阻塞的风险 |
| 加另外一个过期时间(Tim yang) | 1. 保证一致性 | 同上 |
| 不过期(本文) |
1. 异步构建缓存,不会阻塞线程池 |
1. 不保证一致性。 2. 代码复杂度增大(每个value都要维护一个timekey)。 3. 占用一定的内存空间(每个value都要维护一个timekey)。 |
| 资源隔离组件hystrix(本文) |
1. hystrix技术成熟,有效保证后端。 2. hystrix监控强大。 |
1. 部分访问存在降级策略。 |
总结
1. 热点key + 过期时间 + 复杂的构建缓存过程 => mutex key问题
2. 构建缓存一个线程做就可以了。
3. 四种解决方案:没有最佳只有最合适。
Redis缓存雪崩、缓存穿透、热点Key解决方案和分析的更多相关文章
- Redis缓存雪崩,缓存穿透,热点key解决方案和分析
缓存穿透 缓存系统,按照KEY去查询VALUE,当KEY对应的VALUE一定不存在的时候并对KEY并发请求量很大的时候,就会对后端造成很大的压力. (查询一个必然不存在的数据.比如文章表,查询一个不存 ...
- 缓存雪崩、穿透如何解决,如何确保Redis只缓存热点数据?
缓存雪崩如何解决? 缓存穿透如何解决? 如何确保Redis缓存的都是热点数据? 如何更新缓存数据? 如何处理请求倾斜? 实际业务场景下,如何选择缓存数据结构 缓存雪崩 缓存雪崩简单说就是所有请求都从缓 ...
- 什么是redis缓存穿透, 缓存雪崩, 缓存击穿
什么是redis? redis是一个非关系型数据库,相对于其他数据库而言,它的查询速度极快,且能承受的瞬时并发量非常的高.所以常常被用来存放网站的缓存,以减少主要数据库(如mysql)的服务器压力. ...
- 关于redis的几件小事(七)redis缓存雪崩与穿透
1.缓存雪崩 (1)什么是缓存雪崩 缓存雪崩指的是在同一时刻,缓存大量失效,导致大量的请求直接到了数据库,数据库压力剧增,引起系统崩溃.可能出现的情况有: ①大量的key设置了相同的过期时间,导致在缓 ...
- 8.了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?
作者:中华石杉 面试题 了解什么是 redis 的雪崩.穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透? 面试官心理分析 其实这是问到缓存必问的,因为缓 ...
- redis缓存雪崩、穿透、击穿概念及解决办法
缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据 ...
- Java Redis缓存穿透/缓存雪崩/缓存击穿,Redis分布式锁实现秒杀,限购等
package com.example.redisdistlock.controller; import com.example.redisdistlock.util.RedisUtil; impor ...
- Redis 缓存雪崩、穿透、击穿
缓存雪崩 定义: 同一时间所有 key 大面积失效,比如网站首页的数据基本上都是同一批次去缓存的. 解决方法: ① 存的时候设定随机的失效时间. ② 服务做熔断处理(异常或着慢查询 Hystrix 限 ...
- Redis缓存雪崩和穿透的解决方法
转载自: https://blog.csdn.net/qq_35433716/article/details/86375506 如何解决缓存雪崩?如何解决缓存穿透?如何保证缓存与数据库双写时一致的问题 ...
随机推荐
- Spring中通配符问题
一.加载路径中的通配符 (1)?(匹配单个字符) (2)*(匹配除/外任意字符) (3)**/(匹配任意多个目录) 示例: (1)classpath:app-Beans.xml 说明:无通配符,必须完 ...
- elasticSearch6源码分析(7)node
1.node概述 Any time that you start an instance of Elasticsearch, you are starting a node. A collection ...
- JVM学习记录-Java内存模型(二)
对于volatile型变量的特殊规则 关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制. 在处理多线程数据竞争问题时,不仅仅是可以使用synchronized关键字来实现,使用vo ...
- What is AMQP? and the architecture
What is AMQP? (Advanced Message Queuing Protocol) When two applications need to communicate there ar ...
- oracle安装与备份导入
win10安装oracle因运行版本问题导致安装时提示错误(可能win10未被甲骨文公司认证) 跳过的问题 需要更改配置文件: 配置位置在 : 具体操作如下图: 在安装时win10跳过了 许是因为环 ...
- spring 注解@PathVariable
@PostMapping(name="获取用户信息", value="/getUser/{userId}") public Object getUser(@Pa ...
- java工具类-接受请求参数,并利用反射调用方法
public String a(HttpServletRequest request,HttpServletResponse response) throws JSONException, IOExc ...
- Java多线程高级主题
任务定时调度 通过Timer和TimerTask,我们可以实现定时启动某个线程. java.util.Timer:类似闹钟的功能,本身实现的就是一个线程 java.util.TimerTask:一个抽 ...
- Spring、Springmvc整合web的web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:// ...
- webhttpbinding、basichttpbinding和wshttpbinding的区别
webhttpbinding是REST风格的绑定,您只需点击一个URL,然后从Web服务中获取大量XML或JSON. basichttpbinding和wshttpbinding是两个基于SOAP的绑 ...