如何更新缓存吗?如何保证缓存和数据库双写一致性?
admin
2023-04-17 01:21:28
0次

目录

  1. 前言
  2. 先更新数据库,再更新缓存
  3. 先更新缓存,再更新数据库
  4. 先删除缓存,再更新数据库
  5. 先更新数据库,再删除缓存
  6. 删除缓存失败,导致不一致
  7. 读写分离,导致不一致

前言

在项目中缓存是经常用到的,为了减少和数据库的交互,小伙伴们利用缓存的思路如下:

如何更新缓存吗?如何保证缓存和数据库双写一致性?

缓存设计思路

我们小伙伴们有没有考虑到缓存更新的问题,小伙伴们肯定会说肯定用过啊,有数据更新时,把缓存清空掉就行了啊,下一次访问的时候服务就会把新值设置到缓存中了。这样不就行了吗?对的,在一般项目中,这样的使用就够了。那老顾带着大家看看在高并发场景下,会有什么问题?

我们举例说明,就拿商品的库存作为缓存。那现在我们要更新缓存中的库存值,怎么进行操作,我们看下面几个场景:

先更新数据库,再更新缓存

存在的问题场景:请求A更新值为99,请求B更新值为98

如何更新缓存吗?如何保证缓存和数据库双写一致性?

上图流程:

  1. 请求A先发起,更新数据库为99,但还没有来得及更新缓存
  2. 请求B发起,更新数据库为98,又更新了缓存值为98
  3. 请求A这时才更新缓存的值为99

这样数据库的值为98,但缓存的值为99,数值不一致。(不推荐)

先更新缓存,再更新数据库

这个流程跟上面很类似,出现的问题也很类似

  1. 请求A先更新缓存为99,但还没有来得及更新数据库
  2. 请求B更新缓存为98,又更新了数据库为98
  3. 请求A这时更新数据库为99

这样就缓存的值为98,数据库为99导致不一致。(不推荐)

先删除缓存,再更新数据库

存在的问题场景:请求A更新值为99,请求B获取值

如何更新缓存吗?如何保证缓存和数据库双写一致性?

上图中请求流程:

  1. 请求A更新值,先把缓存中的值删除,但还没有来得及更新数据库
  2. 此时请求B过来查询此值,发现缓存中不存在,就到数据库中查询
  3. 请求B在数据库中获取到值,在把值设置到缓存中。
  4. 请求A这时才更新数据库里面的值为99

这样就导致了缓存和数据库的不一致问题,缓存中的值一直是旧数据。(不推荐)

先更新数据库,再删除缓存

这个方案也是老外提出的《Cache-Aside pattern》更新缓存的策略。这种策略先保证了源头的数据一定是正确的。这种策略是不是万无一失呢,有一种非常特殊的场景

如何更新缓存吗?如何保证缓存和数据库双写一致性?

上图流程:建立中缓存突然失效了

  1. 请求A发起查询请求,直接到数据库查询到100,但还没有来得及去设置缓存
  2. 请求B更新值,先更新数据库,在删除缓存
  3. 请求A这时才设置缓存为100

这种情况发生的不一致,是因为缓存突然失效了。而且还要保证请求B更新操作 比 请求A的查询操作还要快;才会导致不一致。这种情况概率会很少。一般要求不高的项目可以采用此方式(推荐)。

缓存删除失败,导致不一致

这种先更新数据库,再删除缓存的策略中,因为要删除缓存,但如果缓存删除失败,就会导致数据库与缓存不一致。这个问题怎么办?我们正常想到的是利用我们MQ中间件去实现。

如何更新缓存吗?如何保证缓存和数据库双写一致性?

上图的流程,如果删除缓存失败,发送消息投递到消息中间件中,进入消息队列。也许有小伙伴就会问,如果消息投递失败怎么办?我们可以利用消息中间件那边的保证100%消息投递的机制(这个以后再讲)。这样就保证了即使删除消息失败,我们也会重试。

不过这个方案有个问题,就是和我们应用服务的业务代码耦合的比较厉害。代码业务不清晰。

那我们有没有别的方案呢,对业务没有侵入呢?

如何更新缓存吗?如何保证缓存和数据库双写一致性?

上图中其实是利用了mysql的底层机制,binlog日志进行删除缓存,这样就不需要和业务关联,删除缓存服务是独立的。我们可以利用阿里开源的canal去操作。

读写分离,导致不一致

这种先更新数据库,再删除缓存的策略是不是就没有问题呢?我们来看一下另一个场景,数据库的读写分离的场景。一般中大型项目都会用到数据库的读写分离。写请求在一个库,读请求在另一个库。读写分离会有个问题,就是库与库之间会存在数据延迟,因为存在数据同步。

那我们再看一下上面的场景流程,就会有问题,因为请求B更新数据 在一个库上面,请求A去读取数据时是另一个库。

  1. 请求B更新值99,删除缓存
  2. 请求A查询值100(读库数据还没有同步),在更新到缓存中(值为100)

这样就导致不一致,这个场景是经常出现的,不是小概率事件。那我们如何处理呢?老顾下次再介绍。

总结:整个导致不一致的原因就是因为高并发情况下各个请求执行的顺序是无法确定的,不知道哪个请求先执行,哪个后执行导致。

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...