雪崩击穿

Redis 的雪崩、穿透和击穿

梦想的初衷 提交于 2020-04-05 19:50:16
缓存雪崩 假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机。缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了。此时,如果没有采用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。 通常我们在使用 Redis 的时候,都会为缓存设置过期时间,但是如果在某个时间点,有大量缓存失效,那么下一个时间点就会有大量请求访问到数据库,这种情况下,数据库可能因为访问量多大导致“崩溃”,这就是缓存雪崩。 第一种情况:缓存雪崩的事前事中事后的解决方案如下: 事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。对于缓存大面积失效的情况可以设置缓存的失效时间使用随机数,避免此问题。 事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。 第二种情况: 不设置缓存过期时间 最暴力的解决办法,缓存不设置自动过期时间,只要缓存不崩,数据库就不会崩。 设置随机过期时间 另外一个办法,就是让缓存过期时间不那么一致,比如一批缓存数据24小时后过期,那么就在这个基础上,让每条缓存的过期时间前后随机 1-6000 秒(1

缓存击穿/雪崩/穿透

偶尔善良 提交于 2020-03-15 06:01:09
网址来源: https://blog.csdn.net/u013067756/article/details/78882440 1. 缓存击穿 对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。 解决方案 1.使用互斥锁(mutex key) 业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。 public String get(key) { String value = redis.get(key); if (value == null) { //代表缓存值过期 //设置3min的超时,防止del操作失败的时候

缓存穿透 击穿 雪崩全解析

孤街浪徒 提交于 2020-02-17 17:48:34
缓存穿透 缓存击穿表示恶意用户模拟请求很多缓存中不存在的数据,由于缓存中都没有,导致这些请求短时间内直接落在了数据库上,导致数据库异常 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。 解决办法 Redis缓存穿透、缓存雪崩、redis并发问题分析 缓存雪崩 缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。 解决办法 缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。 缓存击穿 对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种 非常热点 的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对 某一key 缓存,前者则是

Redis缓存击穿,传统,雪崩

前提是你 提交于 2020-02-15 06:06:35
Redis的三种常见的使用问题 缓存穿透(缓存的数据DB中不存在,缓存中也不存在。但是高频次的无结果查询全部落在DB上,从而影响DB性能) 缓存击穿(当热点数据发生过期时。高频次的访问全部落在DB上,从而影响DB性能) 缓存雪崩(和缓存穿透相似。很多的热点数据同一时间过期。) 缓存穿透 描述: 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。(来自百度百科) 解决方案: 1.缓存空值: 针对空结果查询进行数据缓存,将空结果存入缓存中(设置一个较短的随机过期时间)。 2.布隆过滤器: 是一种较为特殊的数据结构。它实际上是一个很长的 二进制 向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。 布隆过滤器的简单介绍 :他是将每一个key进行hash 算法的,然后存入一个二进制数组当中。 举例 :(假设我们这个布隆过滤器的二进制数组只有10个长度) (我们首先将Alibaba加入到缓存当中) Alibaba ==hash==> 378 (我们将Alibaba进行hash计算后得到378) [0,1,2,3,4,5,6,7,8,9] (我就是一个数组下标

浅谈缓存系统的三个问题

这一生的挚爱 提交于 2020-02-11 11:11:21
缓存雪崩 Cache Avalanche 缓存穿透 Cache Penetration 缓存击穿 Hotspot Invalid 浅谈缓存系统的三个问题 一.无处不在的缓存 缓存在计算机系统是无处不在,在CPU层面有L1-L3的Cache,在Linux中有TLB加速虚拟地址和物理地址的转换,在应用层有Redis等内存数据库缓存、在浏览器有本地缓存、手机有本地文件缓存等等。 可见,缓存在计算机系统中有非常重要的地位,主要作用就是提高响应速度、减少磁盘读取等,本文主要讨论在高并发系统中的缓存系统。一句话概括缓存系统在高并发系统中的地位的话,就是: 如果高并发系统是烤羊肉串,那么缓存系统就是那一撮孜然...... 二.高并发系统中的缓存 缓存系统的作用 缓存系统在高并发系统的作用巨大,没有缓存系统很难支撑C50K(或许这个值已经非常乐观了)以上的场景。 基于机械磁盘或SSD的数据库系统,读写的速度远慢于内存,因此单纯磁盘介质的数据库无法支撑高并发,你可以认为缓存就是为了保护磁盘数据库、是磁盘数据库的屏障。 缓存系统和数据库系统的访问 以读多写少的场景为例(实际场景也是读多写少),看看请求是如何得到响应的,简单流程:请求到达之后,业务线程首先访问缓存,如果缓存命中则返回,如果未命中则继续请求磁盘数据库系统,并将结果回写到缓存系统且增加老化时间

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

半世苍凉 提交于 2020-01-26 11:31:03
1.缓存雪崩 通常我们在数据量请求大或者热点数据都会做缓存,通常情况缓存的数据是通过定时任务刷新,或者查询不到后,通过数据库查询后更新的,定时任务刷新的场景就会有问题,因为所有的key会在同一时间失效,那么在秒杀的场景中,如果缓存失效,大量的请求全部落入数据库,数据库必然是扛不住的,可能还没收到报警,实际上数据库已经宕机了 应对这种场景的处理方法是:1)在批量往redis中存数据的时候,把每个key的失效时间都加一个随机值,这样可以保证不会在同一时间大面积失效。2)电商应用目前使用redis都是集群部署,将热点数据均匀分布在不同的redis分片中也能避免全部失效的问题。3)设置热点数据永不过期,有数据更新时候,就同步更新缓存 2.缓存穿透 如果查询缓存和数据库中都没有的数据,用户不断的发起请求,可能这种用户是攻击者,这种攻击会导致数据库压力过大,严重时会击垮数据库,比如说数据库中的编号都是正数,用户一直用小于0 的参数去请求,每次都是能够绕开缓存世界查库的,数据库也查不到数据,一直这么高并发的请求,通常就很容易挂掉。 应用这种场景的处理方法是:1)接口服务层要增加对参数合法性的校验,不要信任所有的调用者,该防范的还是需要防范 2)对不存在的数据的查询接口也增加缓存,缓存时间可相对控制较短,比如5s等等,这样做可以一定程度的减轻并发情况下的数据库压力 3

redis 缓存穿透、击穿、雪崩

我们两清 提交于 2019-12-06 08:44:50
缓存穿透: 大量查询 redis 中不存在的key(用随救数进行查询),导致每次都会去查询数据库,造成数据库压力过大(甚至宕机)。 解决办法: 1.对我们的 api 接口 进行限流处理、用户授权、黑名单和白名单进行拦截。 2.将不存在的 key 存到 redis 中并设置有效期,有效减轻短时间内重复 key 的查询。不推荐使用(一般随机数都是不相等的)。 3.布隆过滤器 介绍:它实际上是一个很长的 二进制 向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。 缓存击穿: 在高并发的情况下,当一个缓存 key 过期时,因为访问该 key 请求较大,多个请求同时发现缓存过期,因此对多个请求同时数据库查询、同时向Redis写入缓存数据,这样会导致数据库的压力非常大; 1.使用分布式锁 保证在分布式情况下,使用分布式锁保证对于每个key同时只允许只有一个线程查询到后端服务,其他没有获取到锁的权限,只需要等待即可;这种高并发压力直接转移到分布式锁上,对分布式锁的压力非常大。 2.使用本地锁 使用本地锁与分布式锁机制一样,只不过分布式锁适应于服务集群、本地锁仅限于单个服务使用。 3.软过过期 设置热点数据永不过期或者异步延长过期时间; 4.布隆过滤器 缓存雪崩:

缓存雪崩 穿透 击穿

 ̄綄美尐妖づ 提交于 2019-12-05 11:46:51
缓存雪崩   对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机。缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了。此时,如果没有采用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。这就是缓存雪崩。   缓存雪崩的事前事中事后的解决方案如下。 事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。 事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。      用户发送一个请求,系统 A 收到请求后,先查本地 ehcache 缓存,如果没查到再查 redis。如果 ehcache 和 redis 都没有,再查数据库,将数据库中的结果,写入 ehcache 和 redis 中。   限流组件,可以设置每秒的请求,有多少能通过组件,剩余的未通过的请求,怎么办?走降级!可以返回一些默认的值,或者友情提示,或者空白的值。   好处: 数据库绝对不会死,限流组件确保了每秒只有多少个请求能通过。 只要数据库不死,就是说,对用户来说,2/5 的请求都是可以被处理的。 只要有 2/5

缓存中的击穿和缓存中雪崩以及解决方案

守給你的承諾、 提交于 2019-12-02 12:52:27
什么是缓存击穿问题 一些用户在双十一的时候恶意请求一些缓存中不存在的数据,由于一般的逻辑都是查询缓存不存在就切换查数据库,而数据库也不存在,就会抛出大量异常,引起数据库宕机。 解决办法: ①使用互斥锁排队,什么意思?查Redis时为空的时候就加锁,查到数据后再释放锁,其他线程查是空就要再外面 等,这种做法会让吞吐量降低 ②布隆过滤器,什么意思?相当于hashset,快速判断key是否在容器中,如果没有直接返回,这样就不用去查数据库了。 什么是缓存雪崩 击穿是恶意行为,那么雪崩就是过期问题。一个时间段,大量的键过期而导致查不到数据。然后都去访问数据库导 致连接异常。 解决办法: 1.互斥锁 2建议备份缓存 3.修改键过期时间 来源: https://blog.csdn.net/weixin_44787000/article/details/102761319

缓存穿透,缓存击穿,缓存雪崩

£可爱£侵袭症+ 提交于 2019-12-02 01:44:08
本文链接: https://blog.csdn.net/kongtiao5/article/details/82771694 一、缓存处理流程 前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。 二、缓存穿透 描述: 缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。 解决方案: 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截; 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击 三、缓存击穿 描述: 缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力 解决方案: 设置热点数据永远不过期。 加互斥锁,互斥锁参考代码如下: 说明: 1)缓存中有数据,直接走上述代码13行后就返回结果了 2)缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前