2024年Go最新Redis之缓存一致性,开发这么久这些问题都不会

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

总结
理论上先更新DB的线程理应也会先更新缓存,但是并发场景下线程的执行顺序无法保证:

  • 若更新缓存的顺序是: 先线程1再线程2,则不会出现数据不一致问题。
  • 若更新缓存的顺序是: 先线程2再线程1,此时缓存是线程1的数据,DB是线程2的数据,导致缓存和DB数据不一致。

2 并发读写场景
在写线程更新DB和更新缓存之间,读线程可以获取到旧数据,但最终会一致。
具体步骤:

  1. 线程1更新DB
  2. 线程2查询,命中缓存返回
  3. 线程1更新缓存

总结
线程2获取的缓存是旧数据,但最终都会一致。

3.2 先更新DB,后删除缓存

1 并发写场景
所有线程都是先更新DB再删除缓存,无论哪个线程先更新DB再删除缓存,缓存都会被删除,不会导致缓存和DB数据不一致。

具体步骤:

  1. 线程1更新DB
  2. 线程2更新DB
  3. 线程2删除缓存
  4. 线程1删除缓存

总结
无论哪个线程先更新DB再删除缓存,缓存都会被删除,不会导致缓存和DB数据不一致。


2 并发读写场景
在写线程更新DB再删除缓存之间,读线程可以获取到旧数据,但最终会一致。

具体步骤:

  1. 线程1更新DB
  2. 线程2查询命中缓存返回
  3. 线程1删除缓存

总结
线程2获取的缓存是旧数据,但后续最终都会一致。

3.3 先更新缓存,后更新DB

1 并发写场景
所有线程都是先更新缓存再更新DB,在某个写线程更新缓存和更新DB之间,其他写线程也更新了缓存和DB,导致缓存和DB数据不一致。

具体步骤:

  1. 线程1更新缓存
  2. 线程2更新缓存
  3. 线程2更新DB
  4. 线程1更新DB

总结:理论上先更新缓存的线程也会先更新DB,但是并发场景下线程的执行顺序无法保证:

  • 若更新DB的顺序是: 线程1再线程2,则不会出现数据不一致问题。
  • 若更新DB的顺序是: 线程2再线程1,此时缓存是线程2的数据,DB是线程1的数据,导致缓存和DB数据不一致。

2 并发读写场景
在写线程更新缓存和更新DB之间,读线程也可以获取到最新的缓存,不会导致缓存和DB数据不一致。

具体步骤:

  1. 线程1更新缓存
  2. 线程2查询,命中缓存返回
  3. 线程1更新DB

总结
可以保证缓存和DB数据一致,虽然线程1更新DB的操作还没有完成,但是更新缓存的操作已经完成了,读请求可以获取到最新的缓存。

3.4 先删除缓存,后更新DB

1 并发写场景
所有线程都是先删除缓存再更新DB,无论哪个线程先删除缓存再更新DB,缓存都会被删除,不会导致缓存和DB数据不一致。

具体步骤:

  1. 线程1删除缓存
  2. 线程2删除缓存
  3. 线程2更新DB
  4. 线程1更新DB

总结
无论哪个线程先删除缓存再更新DB,缓存都会被删除,不会导致缓存和DB数据不一致。


2 并发读写场景
在写线程删除缓存和更新DB之间,读线程根据查询的DB结果更新了缓存,导致缓存和DB数据不一致。

具体步骤:

  1. 线程1删除缓存
  2. 线程2查询,未命中
  3. 线程2查询DB
  4. 线程2根据查询的DB结果更新缓存
  5. 线程1更新DB

总结:
线程1删除缓存和更新DB之间,线程2根据查询的DB结果更新了缓存,导致缓存和DB数据不一致。

3.5 延迟双删

因为3.4 先删除缓存,再更新DB,在并发读写场景会导致数据不一致。
延迟双删是基于先删除缓存再更新DB的基础上的改进,在更新DB后延迟一定时间,再次删除缓存。

延迟是为了保证第二次删除缓存前能完成更新DB操作,延迟时间根据系统的查询性能而定。
第二次删除缓存是为了保证后续请求查询DB(此时数据库中的数据已是更新后的数据),重新写入缓存,保证数据一致性。

1 并发写场景
无论哪个线程都会删除缓存,所以不会导致缓存和DB数据不一致。

具体步骤:

  1. 线程1删除缓存
  2. 线程2删除缓存
  3. 线程2更新DB
  4. 线程1更新DB
  5. 线程1延时删除缓存
  6. 线程2延时删除缓存

2 并发读写场景
具体步骤:

  1. 线程1删除缓存
  2. 线程2查询,未命中
  3. 线程2查询DB
  4. 线程2根据查询的DB结果更新缓存
  5. 线程1更新DB
  6. 线程1延时删除缓存

总结:
线程1第一次删除缓存之后,线程2根据查询的DB结果更新缓存,此时查询得到的结果是旧数据,线程1延迟第二次删除缓存之后,后续查询DB(此时数据库中的数据已是更新后的数据),重新写入缓存,不会导致缓存和DB数据不一致。


3 延时双删的缺点:

  1. 需要延时,低延时场景不合适,如秒杀等需要低延时,需要强一致,高频繁修改数据场景。
  2. 不能保证强一致性,在更新DB之前,查询线程查询得到的结果是旧数据,可但可以减轻缓存和DB数据不一致的问题。
  3. 延时的时间是一个不可评估的值,延时越久,能规避一致性的概率越大。

3.6 异步删除缓存

因为3.2 先更新DB,后删除缓存 在并发写场景不会导致数据不一致,但是在并发读写场景会短暂的导致数据不一致,但是由于删除缓存失败不会重试,并发写场景、并发读写场景都可能长时间导致数据不一致。

异步删除缓存是对先更新DB,后删除缓存的改进:更新DB之后,基于消费队列异步删除缓存。

根据消费队列不同大致分为:消息队列、bin log+消息队列。

3.6.1 基于消息队列的异步删除缓存

1 并发写场景
无论哪个线程先更新DB再删除缓存,缓存都会被删除,不会导致缓存和DB数据不一致。

具体步骤:

  1. 线程1更新DB
  2. 线程2更新DB
  3. 线程2把删除缓存放入消息队列
  4. 线程1把删除缓存放入消息队列
  5. 异步:消息队列消费删除缓存

总结:
无论哪个线程先更新DB再删除缓存,缓存都会被删除,不会导致缓存和DB数据不一致。

2 并发读写场景
异步删除缓存期间,读线程获取的缓存是旧数据,短暂出现数据不一致,异步删除缓存后最终会一致。

具体步骤:

  1. 线程1更新DB
  2. 线程2查询缓存,命中返回
  3. 线程1把删除缓存放入消息队列
  4. 异步:消息队列消费删除缓存

总结:
异步删除缓存期间,读线程获取的缓存是旧数据,短暂出现数据不一致,异步删除缓存后最终会一致。

3.6.2 基于MySQL的bin log+消息队列删除缓存

1 并发写场景

具体步骤:

  1. 线程1更新DB
  2. 线程2更新DB
  3. 异步:bin log日志收集中间件定时收集DBbin log日志
  4. 异步:bin log日志收集中间件发送日志消息到消息队列
  5. 异步:消息队列消费删除缓存

总结:
无论哪个线程先更新DB再删除缓存,缓存都会被删除,不会导致缓存和DB数据不一致。


2 并发读写场景
具体步骤:

  1. 线程1更新DB
  2. 线程2查询缓存,命中返回
  3. 异步:bin log日志收集中间件定时收集DBbin log日志
  4. 异步:bin log日志收集中间件发送日志消息到消息队列
  5. 异步:消息队列消费删除缓存

总结:
异步删除缓存期间,读线程获取的缓存是旧数据,短暂出现数据不一致,异步删除缓存后最终会一致。

3.6.3 异步删除缓存的优缺点

优点:

img
img
img

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

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

…(img-ZnpH8SLY-1715638651102)]
[外链图片转存中…(img-imUQ3bFx-1715638651103)]
[外链图片转存中…(img-zZgsmG1S-1715638651103)]

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

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 30
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用提供了关于Redis缓存一致性的讨论。缓存一致性是指在使用Redis缓存的情况下,当数据库中的数据发生变化时,需要保证缓存中的数据与数据库中的数据保持一致。解决缓存一致性的方法可以有多种。一种方法是通过主动更新缓存来保持一致性,即在更新数据库之后,手动删除缓存中对应的数据。这样下次查询时就会从数据库中重新获取最新的数据并写入缓存。另一种方法是使用事务来保证原子性,先更新数据库,再删除缓存,保证两个操作的一致性。还有一种方法是使用Redis中的有效时间TTL作为兜底,即设置缓存中的数据在一定时间后过期,这样即使数据在数据库中发生了变化,缓存中的数据也会在过期后被删除,下次查询时会从数据库中重新获取最新的数据并写入缓存。根据具体的需求和系统情况,可以选择适合的方法来解决Redis缓存一致性问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Redis缓存一致性问题(缓存更新策略)](https://blog.csdn.net/Swofford/article/details/129158429)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值