<>缓存请求流程
Redis缓存的雪崩、穿透、击穿属于日常工作中经常会遇到的经典问题,下面来一探究竟,他们的解决方案主要是:布隆过滤器、分布式锁(下次再写)
这是一个简单的客户端、服务端请求Redis的流程图,简单来说就是当用户向服务端进行访问时,服务端如果需要向数据库请求数据时,先去缓存中看有没有,有则直接返回,没有才会再去数据库中查询返回,这是一个正常的缓存流程。
<>缓存雪崩
比如这个某宝的场景,当双十一来临之日,用户的访问量是非常之大的,所以有很多的数据是放进Redis中缓存起来,对应了Redis的key,并且设置了缓存失效时间是三小时,当双十一期间,购物超过三小时之后,缓存同时在一瞬间全部都失效了,导致所有的请求全部打到了数据库上,造成数据库响应不及时而挂掉,这时候就没办法对外提供该服务了。
简单来说:用户访问某宝,Redis中的key大面积失效,导致直接与数据库沟通,这种现象就叫缓存雪崩。
解决方案:
* 设置失效时间,让他不要在同一时间失效,在设置缓存的时候,随机初始化失效时间,这样就不会让所有的缓存在同一时间全部失效,尽可能分散分布。
* Redis一般都是集群部署,我们将热点key放到不同的节点上去,让这些热点缓存平均的分布在不同的节点上。
* 不设置缓存失效时间
* 跑定时任务,不断的刷新缓存,就是当缓存即将失效的时候再去让他延长三小时
<>缓存穿透
这里有个场景,比如有个黑客想攻击我们的网站:
数据库的主键都是从0开始递增,是没有负数的,这个黑客一直用id<0的方式向我们的服务器进行请求,redis自然没有这个id,就会向MySQL进行请求,这样就造成请求不断的打到数据库上,因为Redis并没有拦截id<0的数据,直接被这样的非法请求给穿透了。
简单来说:缓存穿透就是Redis和数据库中都没有这样的数据,一般出现这种情况都不是正常的用户,都是恶意用户。
解决方案:
* 当数据穿透Redis打到数据库上时,数据库返回的空值也要同步到Redis中去,起码保证这个非法id下次请求就直接从Redis中返回了
* (黑客会换不同的非法参数),直接拉黑ip
* (黑客也会换不同的ip),对输入的参数进行合法性校验
* 布隆过滤器
<>缓存击穿
比如这个场景:双十一的时候,把马爸爸的鞋拿出来拍卖,程序员就把鞋的数据放到了Redis缓存中,对应一个key,拍卖的时候,可想而知,大家的热情非常高涨,一直持续了4小时,这个鞋缓存失效了,导致大量的请求查询不到这个鞋的数据,进而全部打到数据库上,造成数据库响应不及时而挂掉。
简单来说:就是击穿某一个非常热点的key
解决方案:
* 让缓存永远不过期(不太好)
*
最好的方式:分布式锁(在请求数据库这一步给上锁,这时候只有一个线程可以抢到锁,也就是只有一个线程能操作数据库,那么这时候数据库的压力就非常小了,当查询到这个热点key后又写会Redis中,其他没有抢到锁的线程,让他先睡几毫秒,再重新去redis中查询数据)
思考:
一个项目可以分为三个阶段,上线前准备、项目运行中的准备、项目宕机后的处理措施。
比如项目上线前,可以给它搭成集群:Redis集群、MySQL集群、本身的分布式集群,这样可以形成高可用集群,增强了系统的健壮性。
项目运行过程中发生的一些问题,可以采用限流降级的处理措施,防止大量请求打到数据库上,造成系统的不可用。
如果系统真的挂掉了,可以集成一些报警系统,即使的通知我们的开发人员,同时快速重启这个项目,利用Redis的aof、rdb持久化机制,去快速的恢复缓存数据,最大限度的去减少系统不可用的时间