一、缓存击穿
如果缓存中的某个热点数据过期了,此时大量的请求访问了该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易就被高并发的请求冲垮,这就是缓存击穿的问题解决方案:
- 互斥锁方案,请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力。
- 不给热点数据设置过期时间,由后台异步更新缓存,或者在热点数据准备要过期前,提前通知后台线程更新缓存以及重新设置过期时间;
二、缓存穿透
当大量请求的数据既不在缓存中,也不在数据库中,导致请求在访问缓存时,发现缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据,没办法重新构建缓存数据,来响应后续的请求。那么当有大量这样的请求到来时,数据库的压力骤增,这就是缓存穿透的问题解决方案:
- 非法请求的限制,如果是url参数有问题或者是恶意攻击请求不存在的数据,可以在API 入口处判断求请求参数是否合理,不合理就限制请求;
- 缓存空值或者默认值,当出现缓存穿透的现象时,可以针对查询的数据,在缓存中设置一个空值或者默认值;
- 使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在;
三、缓存雪崩
通常我们为了保证缓存中的数据与数据库中的数据一致性,会给 Redis 里的数据设置过期时间,当缓存数据过期后,用户访问的数据如果不在缓存里,业务系统需要重新生成缓存,因此就会访问数据库,并将数据更新到 Redis 里,这样后续请求都可以直接命中缓存。那么,当大量缓存数据在同一时间过期(失效)或者 Redis 故障宕机时,如果此时有大量的用户请求,都无法在 Redis 中处理,于是全部请求都直接访问数据库,从而导致数据库的压力骤增,严重的会造成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃,这就是缓存雪崩的问题。
解决方案:
-
均匀设置过期时间;
如果要给缓存数据设置过期时间,应该避免将大量的数据设置成同一个过期时间。我们可以在对缓存数据设置过期时间时,给这些数据的过期时间加上一个随机数,这样就保证数据不会在同一时间过期。 -
互斥锁;
当业务线程在处理用户请求时,如果发现访问的数据不在 Redis 里,就加个互斥锁,保证同一时间内只有一个请求来构建缓存 -
后台更新缓存;
业务线程不再负责更新缓存,缓存也不设置有效期,而是让缓存“永久有效”,并将更新缓存的工作交由后台线程定时更新。
四、总结
简单来说:-
缓存雪崩就是redis中大量key同时过期
-
缓存击穿就是redis中热点数据的key突然过期,虽然不是大量key同时过期,但是因为是热点数据,请求量也非常大
-
缓存穿透就是大量请求的数据既不在redis中,也不在数据库中,比如非法访问,黑客攻击,或者url上乱改参数访问等
参考文档:
https://www.zhihu.com/question/421946305