缓存“延时双删”真的有必要吗?我觉得没有

本文分析了缓存的常见读写模式,包括Cache Aside Pattern、Read/Write Through Pattern和Write Behind Caching Pattern。讨论了缓存更新时先删除后更新的策略,以及延时双删的优缺点。尽管延时双删能减少数据不一致,但增加了系统复杂性,实际应用中需权衡利弊。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

我们在实际的项目中经常会使用到缓存,本文我们主要来总结下缓存的几种常见的读写模式。

缓存的读写模式

Cache Aside Pattern(常用)

Cache Aside Pattern(旁路缓存),是最经典的缓存+数据库读写模式。
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。

image-20210308153152098

更新的时候,先更新数据库,然后再删除缓存 。

image-20210308153239381

**为什么是删除缓存,而不是更新缓存呢? **

原因有两点:

  1. 如果缓存的结构是一个hash或list等,更新数据时需要遍历,比较耗时
  2. 我们对于缓存的要求是懒加载,也就是使用的时候才更新即可。我们可以采用异步的方式填充缓存,比如开启一个线程,定时将DB(数据库)中的数据刷到缓存中去。

高并发脏读的三种情况
1、先更新数据库,再更新缓存
update与commit之间,更新缓存,commit失败
则DB与缓存数据不一致。

再举一例:

1、A更新数据库

2、B更新数据库

3、B写入缓存

4、A写入缓存

本来最终结果应该是B写入缓存才对,而由于网络延迟等原因,导致A与B写入缓存的顺序颠倒,造成数据不一致。

2、先删除缓存,再更新数据库
update与commit之间,有新的读,缓存空,读DB数据到缓存 数据是旧的数据
commit后 DB为新数据
则DB与缓存数据不一致
3、先更新数据库,再删除缓存(推荐)
update与commit之间,有新的读,缓存空,读DB数据到缓存 数据是旧的数据
commit后 DB为新数据
则DB与缓存数据不一致
解决方法:采用延时双删策略

延时双删

为什么采用延时双删?

  1. 假如只先删缓存,会出现在第一个事务更新数据库之前,另一个事务又将旧数据放入缓存的问题,如下图所示:

image-20210309095726117

  1. 假如只后删缓存,那么在更新完数据库之后、更新缓存之前的这段时间内,其他事务的查询都拿到的是旧数据,如下图所示:

image-20210309101009500

  1. 普通双删

存在的问题:第一次清空缓存后,更新数据库前的这段时间内,其他事务查询了数据库的数据,第二次清空缓存后,刚才查询数据库 的那个线程又更新了缓存,此时又会将旧数据更新到缓存。

如下图所示:

image-20210309141557606

  1. 延时双删

在3中,第二次清空缓存之前,多延时一会,等B更新缓存结束了,再删除缓存,这样缓存就不存在了,其他事务查到的就是新缓存。

延时操作是为了确保 修改数据库——>清空缓存前,这段时间内,其他事务的更新缓存操作已完成。

延时删

采用延时删最后一次缓存,但这其中难免还是会大量的查询到旧缓存数据的,如下图所示:

延时双删

这时候可以通过加锁来解决,一次性不让太多的线程都来请求,另外从图上看,我们可以尽量缩短第一次删除缓存和更新数据库的时间差,这样可以使得其他事务第一时间获取到更新数据库后的数据。

Read/Write Through Pattern

Read-Through(穿透读模式/直读模式):应用程序读缓存,缓存没有,由缓存回源到数据库,并写入
缓存。(guavacache采用此种方式)

Write-Through(穿透写模式/直写模式):应用程序写缓存,缓存写数据库。

该种模式需要提供数据库的handler,开发较为复杂。

Write Behind Caching Pattern

描述:应用程序只更新缓存。缓存通过异步的方式将数据批量或合并后更新到DB中
存在的问题:不能时时同步,甚至会丢数据

总结

本文主要学习了缓存的几种读写模式,常用的旁路缓存模式,重点研究了延时双删的策略来减少访问缓存出现的问题。
最后说一句,缓存双删在实际场景中并不常用,因为增加了系统的复杂度,很多时候得不偿失,还是得根据具体的场景来考虑对应的解决方案,看你要具体解决什么问题,分清楚主次,不要一上来就延时双删,只能贻笑大方。

更多我亲身经历的面试真题,还有想要内推大厂的小伙伴可以联系我,请关注微信公众号:【程序员资料站】,回复关键字 “面试” 获取更多面试资料,回复“内推”,我帮你内推大厂。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员资料站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值