开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
使用redis作为缓存时,经常遇到击穿、穿透和雪崩等问题需要解决
击穿
某个key在缓存中不存在,导致大量请求下沉到数据库查询。 如果大量的请求都无法命中缓存,会导致数据库压力突增,从而导致数据库发生宕机的风险
解决方案1:采用同步+双重检查机制
当发现缓存中某个Key不存在时,进入同步代码块,在同步代码块中再次检查key是否存在(双重检查),否则查询数据库并同步到redis缓存,采用同步块以阻止其他请求并发访问数据库。
这种方案有个缺点:发生不存在的缓存时,会阻塞其他线程。
解决方案2:缓存不过期
这种方案可以解决正常的业务缓存过期的问题,但无法实际中缓存会采用FIFO、LFU或LRU等策略对缓存进行过期处理;
另外非正常业务也无法避免,比如大量恶意请求或bug导致请求不存在的缓存,还是无法避免击穿问题,所以要结合穿透的预防策略共同解决。
雪崩
大量key在缓存中失效或不存在,导致高并发请求数据库,造成雪崩;还有一种情况就是redis直接崩了 ...
首先解决穿透的危险,同时可参考击穿的解决思路。
雪崩和击穿的区别:雪崩是多个key同时失效,击穿是一个Key 。
穿透
一般由恶意代码引发,大量请求去请求缓存和数据库都不存在的数据。
可以采用缓存恶意缓存的解决办法,防止恶意代码对同一不存在key进行疯狂轰击;另外可以采用布隆过滤,缓存正常的key,在进行请求之前验证该key的正确性,存在一定的误判。