如何更新缓存吗?如何保证缓存和数据库双写一致性?
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)

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

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

相关内容

热门资讯

英国首相斯塔默再遭逼宫,在内阁... 【文/观察者网 熊超然】在上周经历地方选举惨败后,作为执政党领袖的英国首相斯塔默于当地时间5月11日...
日防相声称:新西兰考虑进口日本... 据凤凰卫视报道,5月12日,日本防卫大臣小泉进次郎在记者会上表示,新西兰已将日本海上自卫队最上型改良...
小米YU7 GT“车厘子红”无... 5 月 12 日消息,博主 @王的男人、昨日晒出了小米 YU7 GT「车厘子红」实车照片。画面显示,...
中关村论坛重磅发布!大兴机场临... 3月27日,在中关村论坛数据跨境流动创新发展论坛上,北京大兴国际机场临空经济区(大兴)正式发布跨境可...
白宫公布随特朗普访华16位商界... 白宫11日公布了将随特朗普一同访华的商界领袖名单。据多家美媒报道,总共将有16位美国商界代表来到北京...
荣耀申请代码生成方法专利,提高... 国家知识产权局信息显示,南京荣耀软件技术有限公司申请一项名为“代码生成方法、电子设备及存储介质”的专...
凤凰连线:中美新一轮经贸磋商,... 中美双方将在韩国举行第七轮经贸磋商。美方的阵容和日程安排如何?在这轮磋商中有哪些关切?凤凰卫视驻韩国...
知情人士:阿联酋秘密打击伊朗,... 据参考消息援引美国《华尔街日报》网站5月11日报道,多名知情人士透露,阿联酋已对伊朗发动军事打击,令...
美防长称美伊停火协议依然有效 △赫格塞思(资料图)当地时间5月12日,美国国防部长赫格塞思表示,他们针对伊朗问题的所有情况都制定了...
特朗普二度来华,五大博弈看点,... 就在5月11日,外交部官宣了一则重磅消息:应中国邀请,美国总统特朗普将于5月13日至15日开启访华行...