前言
在学习redis相关问题时看到的两个问题,想起自己以前面试也遇到过,记录下来以备后用
1.缓存穿透
缓存穿透是指访问一个根本不存在的数据,多次的访问导致数据库压力变大,而缓存没起到作用;缓存穿透问题可能会使后端存储负载加大,由于很多后端存储不具备高并发性,甚至可能造成后端存储宕掉。通常可以在程序中分别统计总调用数、缓存层命中数、存储层命中数,如果发现大量存储层空命中,可能就是出现了缓存穿透问题。
造成缓存穿透的基本有两个。第一,业务自身代码或者数据出现问题,第二,一些恶意攻击、爬虫等造成大量空命中,
解决方案:
1. 对于查询不到的空数据也做缓存,缓存时间可设置短一些,但是存在一些问题,空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间
2. 使用布隆过滤器。在访问缓存层和存储层之前,将存在的 key 用布隆过滤器提前保存起来,做第一层拦截,有关布隆过滤器的相关知识,可以参考:http://www.cnblogs.com/duanxz/p/3480254.html,其实也可以利用 Redis 的 Bitmaps 实现布隆过滤器,GitHub 上已经开源了类似的方案,读者可以进行参考:
https://github.com/erikdubbelboer/Redis-Lua-scaling-bloom-filter
2.缓存雪崩
缓存雪崩是指在同一时间缓存同时失效,有可能是因为过期时间,有可能是因为缓存服务器宕机,此时大量请求进入数据库查询,导致数据库压力剧增。
对于缓存因为过期而同时失效的问题,就需要分析接口调用,尽可能的使缓存过期时间分布均匀。
若是因为缓存服务器宕机,这就涉及到缓存的容灾处理,缓存的高可用,可以参考redis集群搭建,并且可以通过redis的哨兵模式解决。
缓存雪崩简单来说就是缓存失效的问题,业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。