聊聊缓存穿透、雪崩及解决方案
在平常工作中,为了减少数据库的压力,往往我们会将频繁使用的数据查询后写入redis缓存,在下次请求时读取redis获取数据,今天就聊聊使用redis时
可能会遇到的一些问题场景以及解决方案。
一、缓存穿透
1.定义
缓存穿透,指的是当查询不到某一个key的value,程序从而直接进行查询数据库。由于缓存不命中,每次都查询持久层,若数据库量大或者高并发等因
素直接造成的数据库由于压力大而奔溃。
2.解决方案
2.1.读取DB是在缓存未命中的时候进行的动作,不管什么原因,若DB返回的数据为null,都将查询结果进行缓存,且该缓存的过期时间尽可能的短。
$redis = new Redis(); $cache = $redis->get($cacheKey); if(empty($cache)){ //伪代码,从数据库中获取数据。若DB返回为null,也将null值进行缓存 $data = $conn->query($sql); $redis->set($cacheKey, $data, $expire); }
2.2.使用布隆过滤器,布隆过滤器是一种空间效率极高的概率型算法和数据结构,主要用来判断一个元素是否在集合中存在。当一个查询请求过来时,
先经过布隆过滤器进行查,如果判断请求查询值存在,则继续查;如果判断请求查询不存在,直接丢弃。
二、缓存雪崩
1.定义
缓存雪崩,指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至宕机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,
缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
2.解决方案
2.1.从条件“数据大批量到过期时间”出发,在设置缓存的时候给各缓存设置随机过期时间,不让大量key的过期时间一致。
2.2.导致大量数据直接查库的另一种原因是redis挂掉,为了尽量避免redis挂掉,应该实现Redis的高可用(主从架构+哨兵 或者集群),同时设置本
地缓存以及请求限流,尽量避免大流量直接请求数据库造成数据库压力剧增挂掉,进行redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。
慢慢来才是最快的