缓存穿透
什么是缓存穿透?
缓存穿透是指查询大量的key实际不存在
例如:数据库中存储的国内34个省级行政区域信息,id是1-34,缓存的key为id。客户查询35、36、0等等实际不存在的key。因为这些数据实际不存在,所以缓存中也无法命中,便需要服务查询数据库,如果大量此类查询会直接导致数据库扛不住甚至宕机等可能性
解决方案
方案1:将不存在的key缓存起来,超时时间设置得短一些
优点:处理逻辑简单
缺点:仍然可能被攻击,导致内存突然暴涨,因为即使不存在的key都要缓存下来。内存暴涨可能会导致服务宕机
方案2:使用布隆过滤器,将所有存在的key映射至一个bitmap中,通过bitmap过滤掉所有不存在的key的查询
优点:不用缓存没有意义的key。节约内存
缺点:逻辑相对而言较为复杂,需要确保所有的key都映射到bitmap中,也就是每次新增、删除key都需要同步维护bitmap。hash函数的选择,hash冲突问题的处理
缓存雪崩
什么是缓存雪崩?
缓存雪崩是指某个时间点,大量的key超时,导致这些大量的key的查询都打到了后端数据库,导致数据库扛不住甚至宕机等可能性
解决方案
key的超时时间使用某个区间的随机值,或者轮训值。类似负载均衡的算法,使得key的超时时间尽量分散
缓存击穿
什么是缓存击穿?
缓存击穿是指某一个key超时失效时,突然大量的查询都来查询这一个key。导致所有的查询均打到后端数据库上进行更新缓存。导致数据库扛不住甚至宕机等可能性
解决方案
先说解决方案就是查询数据库刷新缓存处增加一个排它锁,保证只有一个客户端去刷新缓存,其他获取所失败的客户端重新尝试从缓存中获取数据
问题的关键点是在于大量的查询都没有命中然后去数据库查询然后更新缓存。而此处的所有的查询与刷新都是针对的同一个key,也就是说其实查询与操作动作都是重复的,只需要一个客户端去查询然后刷新缓存即可。所以使用排它锁即可。
流程图如下
总结
缓存穿透、缓存雪崩都是多个key的场景。缓存击穿是单个key的场景
缓存穿透针对的是实际不存在的key的查询。缓存雪崩、缓存击穿针对的是实际存在的key的查询