文章目录
- 前言
- 一、击穿
- 1.介绍
- 2.产生原因
- 3.解决方案
- 二、穿透
- 1.介绍
- 2.产生原因
- 3.解决方案
- 三、雪崩
- 1.介绍
- 2.产生原因
- 3.解决方案
- 结尾
前言
众所周知,计算机的瓶颈之一就是IO,为了解决内存与磁盘速度不匹配的问题,产生了缓存,将一些热点数据放在内存中,随用随取,降低连接到数据库的请求链接,避免数据库挂掉。需要注意的是,无论是击穿还是后面谈到的穿透与雪崩,都是在高并发前提下,当缓存中某一个热点key失效。
一、击穿
1.介绍
缓存击穿就是在处于集中式高并发访问的情况下,当某个热点 key 在失效的瞬间,大量的请求在缓存中获取不到。瞬间击穿了缓存,所有请求直接打到数据库,就像是在一道屏障上击穿了一个洞。
2.产生原因
- Key 过期
在 Redis 中,key 有过期时间。如果某一时刻(淘宝秒杀,双十一零点开始)key 失效,那么零点之后对某个 key 失效的商品的所有请求将会直接打到数据库上,很有可能倒是数据库崩掉,仅而造成整个服务的不可用。 - Key 被内存淘汰机制淘汰
因为内存是有限的,时时刻刻都有新的缓存数据被放到内存中,而旧的数据被淘汰移除内存。如果开启了 Redis 的内存淘汰机制,Key 会存在被所设置的内存淘汰机制所淘汰的情况。
3.解决方案
- 让这个热点 key 不过期,即不设置失效时间(不推荐)
- 使用分布式锁,如果是单体应用的话使用互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。
二、穿透
1.介绍
对于系统A,假设一秒 5000 个请求,结果其中 4000 个请求是黑客发出的恶意攻击。
黑客发出的那 4000 个攻击,缓存中查不到,每次你去数据库里查,也查不到。
2.产生原因
举个例子。数据库 id 是从 1 开始的,结果黑客发过来的请求 id 全部都是负数。这样的话,缓存中不会有,请求每次都“视缓存于无物”,直接查询数据库。这种恶意攻击场景的缓存穿透就会直接把数据库给打死。
3.解决方案
- 规则排除
可以增加一些参数检验。例如数据库数据 id 一般都是递增的,如果请求 id = -10 这种参数,势必绕过Redis。避免这种情况,可以对用户真实性检验等操作。 - null值填充
当缓存穿透时,redis存入一个类似null的值,下次访问则直接缓存返回空,当数据库中存在该数据的值则需要把redis存在的null值清除并载入新值,此方案不能解决频繁随机不规则的key请求。 - 一级二级缓存法/布隆过滤器
例如布隆过滤器、增强版布隆过滤器、布谷鸟过滤器(布隆过滤器会单独讲解)
三、雪崩
1.介绍
雪崩和击穿类似,不同的是击穿是一个热点 Key 某时刻失效,而雪崩是大量的热点 Key 在一瞬间失效。当大量缓存的过期时间相同时,缓存到达过期时间集体失效或者未加载到内存中,大量请求绕过缓存层直接访问数据库 load 数据,导致数据库频繁 IO,性能下降乃至宕机崩溃。
2.产生原因
- key同时失效
- redis崩溃
3.解决方案
- 优化缓存过期时间
设计缓存时,为每一个 key 选择合适的过期时间,避免大量的 key 在同一时刻同时失效,造成缓存雪崩。 - 使用分布式锁
- 保持缓存层的高可用性
使用Redis 哨兵模式或者Redis 集群部署方式,即便个别Redis 节点下线,整个缓存层依然可以使用。除此之外,还可以在多个机房部署 Redis,这样即便是机房死机,依然可以实现缓存层的高可用。
结尾
- 感谢大家的耐心阅读,如有建议请私信或评论留言。
- 如有收获,劳烦支持,关注、点赞、评论、收藏均可,博主会经常更新,与大家共同进步