1、缓存穿透
查询一个根本不存在的数据,缓存和数据库都不会命中,通常出于容错考虑,如果从数据库查不到数据则不写入缓存。
缓存穿透将导致不存在的数据的每次请求都到数据库中去查询,失去了缓存保护后端的意义。
解决方法:
(1)缓存空对象
数据库查询出来为空,也把空对象缓存到redis中,并且设置过期时间。
(2)布隆过滤器
缓存穿透终极解决方案——布隆过滤器
2、缓存击穿(失效)
由于大批量的缓存在同一时间失效,导致大量的请求同时击穿缓存到达数据库,把数据库打挂掉了。
解决方法:
(1)将一批数据的缓存过期时间设置为一个时间段内的不同时间。
3、缓存雪崩
redis集群忽然挂了(或者请求量超过了redis服务的范围),导致大量的请求直接访问数据库,把数据库打挂了。
解决方法:
(1)保证redis集群的高可用,集群架构,横向扩容;
(2)依赖隔离组件为后端限流熔断并降级;
(3)提前压测演练。
4、热点缓存key重建优化
冷数据没有缓存,突然变成热数据(忽然被直播带货),可能会导致数据库宕机。
解决方法:
从redis拿数据,为空;弄一个分布式锁,只允许一个线程去获取db,建立缓存;
其他线程sleep一段时间,然后再去redis中获取。
5、缓存与数据库双写不一致终极解决:
问题描述:
线程1:写数据库————————————————更新缓存
线程2:——————写数据库————更新缓存——————
解决方法:更新数据库之后立马删除缓存
问题描述:
线程1: 写数据库(10)——删除缓存
线程2:——————————————————————————————————————————写数据库(6)——删除缓存
线程3:————————————————————查缓存(空)—————数据库(10)——————————————————更新缓存
解决方案:
(1)并发几率小的个人数据,很少发生缓存不一致的情况,或者业务可以容忍一小段时间内的不一致,设置超时时间,过一段时间主动更新即可;
(2)如果对于库存等不能容忍不一致的情况,可以通过加读写锁保证并发;读读之间不互斥
(3)通过阿里开源的canal组件,监听数据库的binlog日志,及时的去修改缓存
开源数据同步神器——canal
延时双删:
线程sleep一段时间后再删除一次缓存;