Redis缓存三兄弟(穿透,击穿,雪崩)

缓存穿透

发生情况:redis正常使用情况是当服务器接收一个get请求,请求行携带的id在redis中不存在但是在数据库中存在,就会先查询redis,redis查询不到再查询DB,然后DB返回查询的结果,将返回的数据存储到redis中,但发生穿透时的情况是请求行的id或者其他数据在redis中不存在,在DB中也不存在,这时DB没有返回值,也不能将数据存储在redis中,在这种情况下,当有人恶意发送请求攻击DB,会导致DB崩溃.

解决办法:

1.缓存空数据,查询结果为空时,就将null存进redis中

优点:简单

缺点:消耗内存,可能会发生不一致的问题

2.布隆过滤器: 布隆过滤器可以检测一个数据是否在一个集合中,通过bitmap(位图:相当于一个以bit为单位的数组,每个单元只能存储0或者1).经过多个hash函数获取hash值,再根据hash计算的值在位图对应位置改为1,比如一个数据经过三个hash函数得到1,3,7三个数值,那么位图上三个位置的值从0改成1,当查询这个数据的时候,要再用hash函数算出这三个值并满足这三个位置的值都为1,就说明这个数据存在,再放行给redis,当数据存储过多时,会出现误判,比如数据1存储1,3,7,数据2存储6,9,13,而查询的数据3的hash是3,6,9,那么布隆过滤器会认为这个数据存在在redis或者DB中,这个误差是可接受的,毕竟大部分数据都能够过滤,少部分并不会击垮DB,再结合办法一,DB就很安全了

优点:内存占用少,没有多余的key

缺点:实现复杂,存在误判

缓存击穿

发生情况:redis数据的key存在过期时间,当恰好数据到了过期时间的瞬间,在redis数据重建的空窗大量请求发送过来会瞬间击垮DB

解决方案:

1.互斥锁: 

         线程1:查询缓存未命中,获取互斥锁,查询数据库,并重建缓存数据,写入缓存,释放互斥锁

         线程2:查询缓存未命中,获取互斥锁失败,重试查询缓存未命中,获取互斥锁循环,直到线程1释                       放互斥锁

优点:强一致性

缺点:性能差

2.逻辑过期:

        线程1:查询缓存发现逻辑时间已经过期,获取互斥锁,开启线程2 ,返回过期的缓存数据

        线程2:查询数据库并重建缓存数据,将缓存数据写入redis,重置过期时间,释放锁

        线程3:查询缓存,发现缓存逻辑过期,获取互斥锁失败,返回逻辑过期的数据

优点:性能优,高可用

缺点:不能保证数据绝对一致

缓存雪崩

发生情况:同一时间段大量的缓存key同时失效,或者redis服务宕机,导致大量的请求到达服务器,给DB带来巨大的压力

解决方案:

针对大量缓存key过期: 给不同的key的过期时间TTl添加随机值

针对redis服务宕机: 使用redis集群提高服务的高可用性

给缓存业务添加降级限流策略(保底策略)

给业务添加多级缓存,比如grove当作一级缓存,reids当作二级缓存

<缓存三兄弟>

穿透无中生有key,布隆过滤null隔离

缓存击穿过期key,锁与非锁解难题

雪崩大量过期key,随机时间加集群

面对缓存三兄弟,可用限流来保底

猜你喜欢

转载自blog.csdn.net/DA_YA_/article/details/143381621