Redis机制-Redis缓存穿透,击穿,雪崩理解等问题的理解和学习

目录

[一 缓存穿透问题](#一 缓存穿透问题)

[二 缓存击穿问题](#二 缓存击穿问题)

[三 缓存雪崩问题:](#三 缓存雪崩问题:)


图1 正常的Redis缓存流程

一 缓存穿透问题

我们都知道Redis是一个存储键值对的非关系型数据库,那么当用户进行查询的时候,势必会从前端发起请求,从而数据从Redis缓存中进行查找,查找不到则会在数据库中进行查找。

那么此时就会出现一个问题,就是当有人恶意访问不存在的key时,此时Redis的缓存中没有该值,那么就会一致把请求发送到数据库中。当大量出现上述情况时,此时数据库的负载就会过大,从而发生缓存穿透的问题。

解决方案:

要解决上述问题,一般会使用布隆过滤器或者缓存null值的方法,来避免数据库被攻击。首先我们来讲讲布隆过滤器。

图2 布隆过滤器(详情请查看 布隆过滤器详解Blog

布隆过滤器是搭建在访问Redis服务器之前的,布隆过滤器就是在请求到达Redis之前过滤掉一些Redis缓存中不存在的请求。

图3 位图

首先,请求访问Redis时会携带要访问的key值,此时布隆过滤器会使用不同的hash函数对该key进行哈希,并且存储在位图中,假如每一位都对上了,那么就说明Redis中存在该key那么就可以访问Redis服务器,否则就会直接返回null,从而避免了Redis缓存穿透的问题。

当然,布隆过滤器也会有缺点,就是出现误判的问题,如下图

图4 不同的id误判情况

id=3的数据是不存在的,但是经过不同的hash之后发现,对应的位置恰好为1,那么此时就会出现误判的问题。解决方法当然有,就是增加位图的长度,长度越长误判率就越小,但是此时也出现了额外的内存消耗。当布隆过滤器判断一个元素不存在时,就说明该元素是真的不存在,但是判断存在的时候,也不一定存在。

第二个方法就是在Redis中直接缓存key:null这个键值对,一般时间会设置到5分钟左右,从而避免数据库的压力。当然这样的方式就有些简单粗暴了。

二 缓存击穿问题

当一个热点的key被多个用户频繁访问时,此时如果该key处于过期并且重建的过程中,那么会面临多个请求一起发送到数据库的情况,那么此时就会对数据库造成极大的负载,此时就出现了缓存击穿的问题。

图 5 缓存击穿

针对该问题也有两种方案进行解决,互斥锁和逻辑过期

互斥锁:

图 6 互斥锁

互斥锁是通过对多个线程进行加锁操作从而避免缓存击穿问题的。大致流程如下:

1.当线程1查询缓存时,如果缓存未命中,那么此时就会获取到一把锁,然后去数据库中进行查询数据并且试图重建缓存。

2.线程2也刚好访问该key,它也想拿到锁对数据库进行查询,但是获取锁失败了,就休眠一会再试。

3.当线程1完成一系列操作以后,重建了缓存,此时线程2也可以获取到Redis新建的缓存,那么此时就缓存命中了,就避免了与数据库直接交互的过程,也就避免了缓存击穿的问题。

第二个方法就是逻辑过期

就是将热点的key不设置过期时间。

图 7 逻辑过期

如图:

1.当线程1查询数据时,会获取到互斥锁,然后返回过期数据

2.但是在此之间它还会开启一个新的线程2来重建缓存,重置逻辑过期时间

3.当线程2重写缓存时,线程3刚好来访问,那么线程3会返回一个过期的数据

4.当线程4来访问的时候,因为是在线程2释放锁之后进行的,所以线程4获取的是新的数据。

这就是逻辑过期的原理。

看到这里,其实肯定有疑问,为什么我不选择互斥锁,而选择逻辑过期呢?

其实这还和使用场景有关系,比如说,当写转账,或者京东,淘宝这种秒杀逻辑时,就需要数据的强一致性,那么就需要使用互斥锁,但是一些其他的场景,则有可能用历史的数据就可以完成。那么逻辑过期就可以解决这个问题。主要还是具体场景具体用法。

三 缓存雪崩问题:

听起来名字很可怕,雪崩,但是其实也是由于大量缓存的key同时失效或者Redis服务器宕机所带来的问题,请求会直接到达数据库,从而产生巨大的压力。

图8 缓存雪崩

解决方案:

1.给不同的key添加所及的TTL值:可以让不同的key不会同时达到过期时间。

2.利用Redis集群来提高服务的可用性:比如哨兵模式,主从模式等等

3.给缓存业务添加降级限流策略(系统保底策略。可以解决上面提到的三个问题)

4.添加多级缓存

相关推荐
Jay_fearless40 分钟前
Redis SpringBoot项目学习
spring boot·redis
Wang's Blog1 小时前
Redis: 集群环境搭建,集群状态检查,分析主从日志,查看集群信息
数据库·redis
容器( ु⁎ᴗ_ᴗ⁎)ु.。oO1 小时前
MySQL事务
数据库·mysql
cyt涛3 小时前
MyBatis 学习总结
数据库·sql·学习·mysql·mybatis·jdbc·lombok
Rookie也要加油3 小时前
01_SQLite
数据库·sqlite
liuxin334455664 小时前
教育技术革新:SpringBoot在线教育系统开发
数据库·spring boot·后端
看山还是山,看水还是。4 小时前
MySQL 管理
数据库·笔记·mysql·adb
fishmemory7sec4 小时前
Koa2项目实战2(路由管理、项目结构优化)
数据库·mongodb·koa
momo小菜pa4 小时前
【MySQL 09】表的内外连接
数据库·mysql
Jasonakeke5 小时前
【重学 MySQL】四十九、阿里 MySQL 命名规范及 MySQL8 DDL 的原子化
数据库·mysql