Redis缓存:淘汰机制、缓存雪崩、数据不一致,都一步说到位

Redis缓存模式

Redis缓存模式基于是否接收写请求,可以分成只读缓存和读写缓存:

只读缓存:只处理读操作,所有的更新操作都在数据库中,这样数据不会有丢失的风险。

  • Cache Aside模式

读写缓存,读写操作都在缓存中执行,出现宕机故障,会导致数据丢失。缓存回写数据到数据库有分成两种同步和异步:

  • 同步:访问性能偏低,其更加侧重于保证数据可靠性

  • Read-Throug模式

  • Write-Through模式

  • 异步:有数据丢失风险,其侧重于提供低延迟访问

  • Write-Behind模式

Cache Aside模式

查询数据先从缓存读取数据,如果缓存中不存在,则再到数据库中读取数据,获取到数据之后更新到缓存Cache中,但更新数据操作,会先去更新数据库种的数据,然后将缓存种的数据失效。

而且Cache Aside模式会存在并发风险:执行读操作未命中缓存,然后查询数据库中取数据,数据已经查询到还没放入缓存,同时一个更新写操作让缓存失效,然后读操作再把查询到数据加载缓存,导致缓存的脏数据。

Read/Write-Throug模式

查询数据和更新数据都直接访问缓存服务,缓存服务同步方式地将数据更新到数据库。出现脏数据的概率较低,但是就强依赖缓存,对缓存服务的稳定性有较大要求,但同步更新会导致其性能不好。

Write Behind模式

查询数据和更新数据都直接访问缓存服务,但缓存服务使用异步方式地将数据更新到数据库(通过异步任务) 速度快,效率会非常高,但是数据的一致性比较差,还可能会有数据的丢失情况,实现逻辑也较为复杂。

在实际项目开发中根据实际的业务场景需求来进行选择缓存模式。那了解上述后,我们的应用中为什么需要使用到redis缓存呢?

在应用使用Redis缓存可以提高系统性能和并发,主要体现在

  • 高性能:基于内存查询,KV结构,简单逻辑运算
  • 高并发: Mysql 每秒只能支持2000左右的请求,Redis轻松每秒1W以上。让80%以上查询走缓存,20%以下查询走数据库,能让系统吞吐量有很大的提高

虽然使用Redis缓存可以大大提升系统的性能,但是使用了缓存,会出现一些问题,比如,缓存与数据库双向不一致、缓存雪崩等,对于出现的这些问题该怎么解决呢?

使用缓存常见的问题

使用了缓存,会出现一些问题,主要体现在:

  • 缓存与数据库双写不一致
  • 缓存雪崩: Redis 缓存无法处理大量的应用请求,转移到数据库层导致数据库层的压力激增;
  • 缓存穿透:访问数据不存在在Redis缓存中和数据库中,导致大量访问穿透缓存直接转移到数据库导致数据库层的压力激增;
  • 缓存击穿:缓存无法处理高频热点数据,导致直接高频访问数据库导致数据库层的压力激增;
缓存与数据库数据不一致

只读缓存(Cache Aside模式)

对于只读缓存(Cache Aside模式), 读操作都发生在缓存中,数据不一致只会发生在删改操作上(新增操作不会,因为新增只会在数据库处理),当发生删改操作时,缓存将数据中标志为无效和更新数据库 。因此在更新数据库和删除缓存值的过程中,无论这两个操作的执行顺序谁先谁后,只要有一个操作失败了就会出现数据不一致的情况。

总结出,当不存在并发的情况使用重试机制(消息队列使用),当存在高并发的情况,使用延迟双删除(在第一次删除后,睡眠一定时间后,再进行删除),具体如下:

操作顺序是否高并发潜在问题现象应对方案
先删除缓存,再更新数据库缓存删除成功,数据库更新失败读到数据库的旧值重试机制(数据库更新)
先更新数据库,再删除缓存数据库更新成功,缓存删除失败读到缓存的旧值重试机制(缓存删除)
先删除缓存,再更新数据库缓存删除后,尚未更新数据库,有并发读请求并发读请求读到数据库旧值,并更新到缓存,导致之后的读请求读到旧值延迟双删()
先更新数据库,再删除缓存数据库更新成功,尚未删除缓存读到缓存的旧值不一致的情况短暂存在,对业务影响较小

NOTE:

延迟双删除伪代码:

redis.delKey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)

读写缓存(Read/Write-Throug、Write Behind模式 )

对于读写缓存,写操作都发生在缓存中,后再更新数据库,只要有一个操作失败了就会出现数据不一致的情况。

总结出,当不存在并发的情况使用重试机制(消息队列使用),当存在高并发的情况,使用分布锁。具体如下:

操作顺序是否高 并发潜在问题现象应对方案
先更新缓存,再更新数据库缓存更新成功,数据库更新失败会从缓存中读到最新值,短期影响不大重试机制(数据库更新)
先更新数据库,再更新缓存数据库更新成功,缓存更新失败会从缓存读到旧值重试机制(缓存删除)
先更新数据库,再更新缓存写+读并发线程A先更新数据库,之后线程B读取数据,之后线程A更新缓存B会命中缓存,读取到旧值A更新缓存前,对业务有短暂影响
先更新缓存,再更新数据库写+读并发线程A先更新缓存成功,之后线程B读取数据,此时线程B命中缓存,读取到最新值后返回,之后线程A更新数据库成功B会命中缓存,读取到最新值业务没影响
先更新数据库,再更新缓存写+写并发线程A和线程B同时更新同一条数据,更新数据库的顺序是先A后B,但更新缓存时顺序是先B后A,这会导致数据库和缓存的不一致数据库和缓存的不一致写操作加分布式锁
先更新缓存,再更新数据库写+写并发线程A和线程B同时更新同一条数据,更新缓存的顺序是先A后B,但是更新数据库的顺序是先B后A,这也会导致数据库和缓存的不一致数据库和缓存的不一致写操作加分布式锁
缓存雪崩

缓存雪崩,由于缓存中有大量数据同时过期失效或者缓存出现宕机,大量的应用请求无法在 Redis 缓存中进行处理,进而发送到数据库层导致数据库层的压力激增,严重的会造成数据库宕机。

对于缓存中有大量数据同时过期,导致大量请求无法得到处理, 解决方式:

  • 数据预热将发生大并发访问前手动触发加载缓存不同的key, 可以避免在用户请求的时候,先查询数据库
  • 设置不同的过期时间,让缓存失效的时间点尽量均匀
  • 双层缓存策略, 在原始缓存上加上拷贝缓存,原始缓存失效时可以访问拷贝缓存,且原始缓存失效时间设置为短期,拷贝缓存设置为长期
  • 服务降级 , 发生缓存雪崩时,针对不同的数据采取不同的降级方案 ,比如,非核心数据直接返回预定义信息、空值或是错误信息

对于缓存出现宕机,解决方式:

  • 业务系统中实现服务熔断或请求限流机制,防止大量访问导致数据库出现宕机
缓存穿透

缓存穿透,数据在数据库和缓存中都不存在,这样就导致查询数据,在缓存中找不到对应key的value,都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。

当有大量访问请求,且其绕过缓存直接查数据库,导致数据库层的压力激增,严重的会造成数据库宕机。

对于缓存穿透,解决方式:

  • 缓存空值或缺省值,当一个查询返回的数据为空时, 空结果也将进行缓存,并将它的过期时间设置比较短,下次访问直接从缓存中取值,避免了把大量请求发送给数据库处理,造成数据库出问题。
  • 布隆过滤器( BloomFilter ),将所有可能查询数据key哈希到一个足够大的bitmap中 , 在查询的时候先去BloomFilter去查询key是否存在,如果不存在就直接返回,存在再去查询缓存,缓存中没有再去查询数据库 ,从而避免了数据库层的压力激增出现宕机。
缓存击穿

缓存击穿,针对某个访问非常频繁的热点数据过期失效,导致访问无法在缓存中进行处理,进而会有导致大量的直接请求数据库,从而使得数据库层的压力激增,严重的会造成数据库宕机。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

关于面试刷题也是有方法可言的,建议最好是按照专题来进行,然后由基础到高级,由浅入深来,效果会更好。当然,这些内容我也全部整理在一份pdf文档内,分成了以下几大专题:

  • Java基础部分

  • 算法与编程

  • 数据库部分

  • 流行的框架与新技术(Spring+SpringCloud+SpringCloudAlibaba)

这份面试文档当然不止这些内容,实际上像JVM、设计模式、ZK、MQ、数据结构等其他部分的面试内容均有涉及,因为文章篇幅,就不全部在这里阐述了。

作为一名程序员,阶段性的学习是必不可少的,而且需要保持一定的持续性,这次在这个阶段内,我对一些重点的知识点进行了系统的复习,一方面巩固了自己的基础,另一方面也提升了自己的知识广度和深度。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
识点进行了系统的复习,一方面巩固了自己的基础,另一方面也提升了自己的知识广度和深度。**
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 13
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值