Redis 缓存穿透,缓存击穿,缓存雪崩 & 布隆过滤器
缓存穿透
缓存穿透:指在redis缓存中不存在数据,这个时候只能去访问持久层数据库,当用户很多时,缓存都没有命中就会照成很大压力
解决方案 :
(1)布隆过滤器(对可能查询的数据先用hash存储)
(2)缓存空对象:在没有的数据中存一个空,而这些空的对象会设置一个有效期)
缓存击穿
缓存击穿指的是缓存中没有数据但数据库中有数据(一般是热点数据缓存时间到期),同一时间大量的并发请求由于读缓存没读到数据,就去数据库去取数据,导致某个时间内数据库压力剧增,导致崩溃。
缓存击穿的解决方案:
1.设置热点数据永远不过期(可以判断当前key快要过期时,通过后台异步线程在重新构建缓存)
2.接口限流与熔断,降级。重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,当接口中的某些服务不可用时候,进行熔断,失败快速返回机制。
3.设置互斥锁。在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。
(可以使用 Redis 分布式锁)
(1) 就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db。
(2) 先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX)去set一个互斥锁。
(3) 当操作返回成功时,再进行load db的操作,并回设缓存,最后删除mutex key;
(4) 当操作返回失败,证明有线程在load db,当前线程睡眠一段时间再重试整个get缓存的方法。
缓存雪崩
缓存雪崩:在某个时间段,缓存集体过期、redis宕机
解决方案:给key的失效时间设置为随机时间,避免集体过期;双缓存;加互斥锁
解决方式:
① 若是由于大量key过期所造成的,可以给key的ttl设置随机时间,避免集体过期
② 若是因为redis服务器宕机所导致的,可以搭建redis集群,保证高可用
③ 可以从请求量层面进行解决,对缓存业务添加限流和服务降级策略
④ 可以添加多级缓存,比如说nginx缓存
布隆过滤器
我们可以这样考虑,可以先判断key值是否存在,如果不存在,则不访问redis,那这样就可以拦截大量的请求,布隆过滤器恰好可以实现这样的需求。
布隆过滤器本质是一个二进制向量,初始化的时候每一个位置都是0,如下图,比如说a经过hash算法后得到一个下标位置,接下来就会把下标的值改为1,图中所示的是每一个元素经过三次hash运算,每一个红线代表一次hash算法,为什么要运算三次呢,这是为了减少hash冲突,当然hash算法不一定是三次,经过多次不同维度的哈市算法后,就把a值映射到了二进制向量里面,这样的好处很多,可以节省空间,假如说a值是一串很长的字符串,那么经过映射后就可以只占三位长度,并且查找速度很快。
如果布隆过滤器判断元素存在,则不一定存在,如果不存在,则一定不存在
如何理解这句话,因为有可能你一个元素运算得到的下标恰好是别的元素的下标,如果经过运算后布隆过滤器判断不存在,也就是说至少有一个下标是为0的,那肯定是不存在的
布隆过滤器的使用
用Google的guava包已经有了布隆过滤器算法的实现,注意的是布隆过滤器有一定的误判率,不可能达到100%的精准,首先初始化项目的时候从数据库查询出来所有的key值,然后放到布隆过滤器中,guava包都实现了相应的put方法和hash算法。
加了布隆过滤器的过程如下
1,当应用访问的时候,先去布隆过滤器中判断kedy值,如果发觉没有key值不存在,直接返回
2、如果key值在布隆过滤器存在,则去访问redis,由于是有误判率的,所以redis也有可能不存在
3、那么这时候就去访问数据库,数据库不存在,那就直接返回空就行
如果误判率为3%,当有100万个请求同时过来的时候,布隆过滤器已经挡住了97万个请求,剩下3万个请求假如是误判的,这时候再访问数据库可以通过加锁的方式实现,只有竞争到锁了就去访问数据库,这样就完全可以解决缓存穿透问题
布隆过滤器的应用
比如说输入用户名的时候,可以马上检测出该用户名是否存在,黑名单机制,单词错误检测等
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了