缓存雪崩
问题分析
当缓存集中在一段时间内失效 或者缓存服务器出现宕机,所有的请求都直接落入了数据库中, 导致数据库扛不住,造成数据库挂掉
解决方案
-
事前 Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
-
事中
- 本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
- 通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存
-
事后 Redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据
缓存穿透
问题分析
查询一个一定不存在的数据,缓存查不到,再去数据库查也查不到, 这样的请求每次视缓存于无物
,直接查询数据,当该类流量大量流入或者恶意攻击的场景缓存穿透就直接把数据库打死。
解决方案
- 在数据库中没有查到数据,就写一个空值到缓存中去(比如 set -999 UNKNOWN),然后设计一个过期时间。
缓存击穿
问题分析
缓存击穿,就是说某个热点 key ,访问非常频繁,处于集中式高并发访问的情况,当这个key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。
解决方案
- 若缓存的数据是基本不会发生更新的,则可尝试将该热点数据设置为永不过期。
- 若缓存的数据更新不频繁,且缓存刷新的整个流程耗时较少的情况下,则可以采用基于Redis、zookeeper 等分布式中间件的分布式互斥锁,或者本地互斥锁以保证仅少量的请求能请求数据库并重新构建缓存,其余线程则在锁释放后能访问到新缓存。
- 若缓存的数据更新频繁或者在缓存刷新的流程耗时较长的情况下,可以利用定时线程在缓存过期前主动地重新构建缓存或者延后缓存的过期时间,以保证所有的请求能一直访问到对应的缓存