一、数据一致性(无法做到绝对一致)
缓存分成读写缓存和只读缓存
读写缓存写回策略有两种
1、同步直写策略:写缓存时,也同步写数据库,缓存和数据库中的数据一致;(要在业务应用中使用事务机制,来保证缓存和数据库的更新具有原子性)
2、异步写回策略:写缓存时不同步写数据库,等到数据从缓存中淘汰时,再写回数据库。使用这种策略时,如果数据还没有写回数据库,缓存就发生了故障,那么,此时,数据库就没有最新的数据了。
只读缓存
删除缓存值或者更新数据库值失败
解决方案:重试机制确保删除或者更新操作成功
流程如下图所示:
(1)更新数据库数据
(4)另起一段非业务代码,获得该信息
(6)将这些信息发送至消息队列
(7)重新从消息队列中获得该数据,重试操作。
删除缓存、更新数据库时其他线程的并发读操作
情况一:先删除缓存,再更新数据库。
解决方案:延时双删策略(延时多久不太好确定)
情况二:先更新数据库值,再删除缓存
一种场景是:(期间请求量不会很多,所以影响还好)
另一种场景是:一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生(主从分离,读应该比写快,如果下列场景出现的概率极低)
(1)缓存刚好失效
(3)请求B将新值写入数据库
(4)请求B删除缓存
(5)请求A将查到的旧值写入缓存
解决方案:延时双删策略(延时多久不太好确定,操作,删key,延时,删key)
注意:以上场景,MysqL主从分离也可能会导致(主从延时),所以延时要加上主从延时时长
参考资料:https://blog.csdn.net/sufu1065/article/details/108459758
二、缓存雪崩
缓存雪崩是指大量的应用请求无法在 Redis 缓存中进行处理,紧接着,应用将大量请求发送到数据库层,导致数据库层的压力激增
第一个原因是:缓存中有大量数据同时过期,所有请求达到了数据库上
解决方案:1.不要设置同样的过期时间,可以加上一些随机数值,2.服务降级:只让核心数据去请求应用,非核心数据禁止访问缓存和数据库 3、热点数据不过期
第二个原因是:Redis 缓存实例发生故障宕机了,无法处理请求,这就会导致大量请求一下子积压到数据库层,从而发生缓存雪崩。(一个 Redis 实例可以支持数万级别的请求处理吞吐量,而单个数据库可能只能支持数千级别的请求处理吞吐量)
解决方案:1.在业务系统中实现服务熔断或请求限流机制。2.主从节点(主节点宕机,从节点切换成主节点继续提供服务)
三、缓存击穿
缓存击穿是指,针对某个访问非常频繁的热点数据的请求,无法在缓存中进行处理,紧接着,访问该数据的大量请求,一下子都发送到了后端数据库,导致了数据库压力激增,会影响数据库处理其他请求。缓存击穿的情况,经常发生在热点数据过期失效时,如下图所示
解决方案:不给热点数据设置过期时间,一直保留
缓存雪崩与缓存击穿的区别
缓存雪崩是因为大面积的缓存失效,打崩了DB,而缓存击穿不同的是缓存击穿是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。
四、缓存穿透
缓存穿透是指要访问的数据既不在 Redis 缓存中,也不在数据库中,导致请求在访问缓存时,发生缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据
解决方案:1、接口前面加上校验,去掉不合法的请求,2、缓存空值或缺省值。一旦发生缓存穿透,我们就可以针对查询的数据,在 Redis 中缓存一个空值。查询时就可以直接从 Redis 中读取空值,返回给业务应用了,避免了把大量请求发送给数据库处理(时间要设置的短一些)。3、使用布隆过滤器快速判断数据是否存在,避免从数据库中查询数据是否存在,减轻数据库压力。
- 事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
- 事中:本地 ehcache 缓存 + Hystrix 限流+降级,避免 MysqL 被打死。
- 事后:Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
参考资料:https://segmentfault.com/a/1190000022029639
五、布隆过滤器
布隆过滤器可以检查值是 “可能在集合中” 还是 “绝对不在集合中”。“可能” 表示有一定的概率,也就是说可能存在一定为误判率。
参考资料:https://juejin.cn/post/6844904007790673933
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。