前言:
这是我参加工作之后,第一次开始写博客,我也不知道自己是怎么了,就突然想在网上沉淀点自己的东西,可能是平时在网上拿来主义太多,让我有点不太好意思吧。也可能是最近出去面试了几家公司,发现自己这两年都是在业务代码,对于底层的沉淀太少,虽然业务代码对我来说,没什么问题,但是只要涉及到底层的东西,我就会哑口无言,才让我痛下决心,一定要沉淀点属于自己的东西。不管怎么样,今天开始了这个博客,希望自己能够坚持住,保持自己的初心,持续更新技术和自己生活中的乐趣。共勉!!!
一. 背景
多情的人就喜欢矫情,在开始正题之前,先小小的矫情一下,最近在面试的时候,突然整理到有关缓存穿透、雪崩的一些事情,觉得以后意义,虽然在后面的面试中,没有问到,但是我还是觉得非常有意义的,在这里分享下大家,至于是取自那几位大神的博客,我有点忘记了,在这里标注下,这不是我的原创,我只是机械将大神们说的东西,聚到一起,希望大神看到后莫怪,不喜欢的猿猿们,也请你们不要喷我,再次感谢大家!
二.开始正题
1.缓存穿透:
请求去查询一条缓存和数据库都不存在的数据,每次请求都会请求到数据库上,这种查询不到数据的现象称为缓存穿透。大量的请求到数据库,瞬时间给数据库很大的压力,造成数据库宕机。
解决办法:
1.设置缓存空值,将这些key设置成null,放在缓存中,这样当再次请求的时候,就不会去查询数据库,并设置过期时间。
2.BloomFilter,类似一个hbase set用来判断某个元素(key)是否存在于某个集合中,在缓存之前加一个BloomFilter去查询key是否存在,如果不存在就直接返回,存在再走查缓存查数据库的操作。
2.缓存击穿:
在高并发的场景中,大量请求同时查询一个key,而正好此时,这个key失效了,就会导致大量的请求到数据库,这种现象称为缓存击穿。危害就是会造成某一时刻数据库请求量过大,数据库压力剧增,容易造成宕机的危险。
3.缓存雪崩:
某一个时刻缓存大规模失效,会有大量的请求直接打到DB上面,DB撑不住造成宕机。
解决方法:
1.事前:使用集群缓存,保证缓存服务的高可用,如果使用redis,可以使用主从+哨兵,redis Cluster来避免reids全盘崩溃的情况。
2.事中:ehcache本地缓存 + Hystrix限流&降级,避免mysql被打死。使用预备缓存通道ehcache,并加上限流加入大量的请求到数据库。
3.事后:开启redis持久化机制,尽快恢复缓存集群一旦重启,就能从磁盘上自动加载数据恢复内存中的数据。
最后:
1.在给redis设置过期时间时,设置不同的过期时间,防止缓存在同一时间失效。
2.互斥锁,在BD上加一个互斥锁,但是这个锁会影响DB的性能,需要结合实际的业务去考虑。