文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-04-02 19:55

关注

目录

  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)

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

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯