【IT老齐062】缓存一致性如何保障?先写库还是先写缓存?聊聊Cache Aside Pattern与延迟双删

作者: IT老齐分类: 计算机技术 发布时间: 2021-10-24 21:12:54 浏览:38232 次

【IT老齐062】缓存一致性如何保障?先写库还是先写缓存?聊聊Cache Aside Pattern与延迟双删

林XiaoYi:
老齐 调优怎么全都没了 想攒在一起看的[大哭]

【回复】回复 @毛若昕 :老哥,可以分享一下不
【回复】回复 @毛若昕 :求分享!
微尘带你见世面:
我的理解是 延迟双删的目的是为了避免CAP极端情况下线程1删缓存删了个寂寞,线程2把旧数据缓存起来了,导致不一致的窗口期变长,实际上就是先删缓存再更新库的情况。那可不可以先删缓存再更新库,然后模拟延迟双删发个延迟消息在删一次缓存呢?

【回复】但是如果你线程一先删缓存,删完之后线程二才进来查缓存,发现没有缓存就到库里面去查(此时线程一还没有更新数据),然后把旧数据读到缓存中,依然有可能会造成缓存不一致的问题。我是想,线程一在开启定时任务来删缓存的间隔时期之内,能不能做一个禁止读缓存,但是可以写缓存的操作,那么用户就读不了错误的数据了,只能等待定时任务结束之后再去读取数据,此时基本上所有的数据都是最新的了
【回复】回复 @蒲公英不是梦 :而且延迟双删解决的问题是在数据库更新了之后,也删除了缓存,某个线程把旧数据又放进了缓存,删写删显然不能解决吧,如果一定要先删,就变成删写删删了。
【回复】回复 @蒲公英不是梦 :先删缓存,然后还没更新数据库就被其他线程又将数据据读到旧缓存中,然后再更新数据库。。你这第一次删又有什么意义呢?相当于还是先改动了数据库。。。
小禾先生o:
真的干货,看文章五花八门,一脸懵逼,一看了视频就阔然开朗[微笑]

【回复】哈哈 谢谢兄弟的支持呀
IT老齐:
架构300讲所有课件可以关注 IT老齐 公众号自行下载 QQ交流群:369531466 欢迎一起来玩啊

【回复】老齐,如果我们参考mysql中,脏页数据和磁盘数据的一致性,是不是可以通过更改我们服务器里面的线程模型,来达到数据一致性呢,这样是不是也是一个好的方案呢
【回复】回复 @MinDOYO : MySQL也是参考了操作系统的内存策略,标记脏数据,在需要替换时回写,但是不可能在应用层面玩这一套,一旦Redis没了,意味着对应的数据库数据全部丢失,损失无法预估,肯定不行
Koruss:
先删缓存再更新 和 先更新再删缓存 都有一个不一致的时间窗口,那为什么前面讲的先删缓存再更新,然后再延时双删一次,这种方案不被采用呢?

【回复】线程1 删写删 会可能导致 线程2读缓存为空触发写操作。如果这时候 线程1 写操作没完成, 那么线程2写操作就是旧数据并且要持续5秒。 如果采用双删,那么第一次删除失败, 证明线程二还没完成写操作(这个有耗时),第二次5秒后删除。 差别在于 删写删触发来就固定是5秒数据不同步,而写删删 最多5秒。
【回复】缓存操作失败要忍受(不知道实践中对缓存操作是不是要重试,考虑有重试保证操作能成功或者不保证操作能成功,又增加了弄清楚这个问题的难度),数据库操作失败了肯定要返回失败,所以缓存与数据库的操作顺序也受这个影响。虽然正常运行的系统失败的概率很小,但要应用必须要考虑操作失败带来的影响,提前一些潜在的风险和问题,在分布式事物中只要操作失败了就回滚,反倒简单了。缓存与数据库一致性的问题可以写一篇论文,不知道有没有人写过,之前研究这个问题的时候网上文章特别多,看得很晕,就记住了cache aside是一种大家普遍认可的方案。
【回复】如果删缓存失败了,程序就要退出,但业务操作还是以数据库为主,如果更新数据库退出是比较合理的,更新完数据库删缓存失败也没关系,缓存有过期时间。 另外看大家都是从一致性角度考虑的,这个地方我有点说不清,但我感觉大家好像低估了缓存与数据库一致性这个问题的难度,这个问题看似简单,实际上比分布式事物还难,分布式事物有协调者某个失败了大不了回滚,但这个问题缓存删除失败了或者写入失败了就要忍受,在这个基础上再去比较各种方案带来的一致性问题。
Jiang_zyj:
但是如果你线程一先删缓存,删完之后线程二才进来查缓存,发现没有缓存就到库里面去查(此时线程一还没有更新数据),然后把旧数据读到缓存中,依然有可能会造成缓存不一致的问题。我是想,线程一在开启定时任务来删缓存的间隔时期之内,能不能做一个禁止读缓存,但是可以写缓存的操作,那么用户就读不了错误的数据了,只能等待定时任务结束之后再去读取数据,此时基本上所有的数据都是最新的了

枫色幻想123:
齐老师,之前马士兵VIP的Docker课程是您教的么?翻视频课的时候正好看到[狗子]

小禾先生o:
这样删除缓存是否查询判断也要做锁 因为缓存删除后有比较多的请求同时进入的话 都还没写回缓存的时候 会有缓存击穿风险是吗

【回复】查询该加锁还是要加锁 这里说的问题是修改时,缓存与数据库不一致的解决方案
jonathan__:
会存在击穿的情况,但是一般环境这种方式没问题

【回复】读的时候缓存没有,查数据库得加锁
得闲一起收衫:
Cache Aside Pattern 不一致情况的例子里,把线程2的查缓存阶段去掉会不会好一点?感觉这样比较不容易误导大家。 其实导致这种不一致的情况的根本原因就是删除缓存在设置历史缓存之前(更新数据库操作刚好卡在缓存设置中间)。延迟再删一次的目的就是把这个错误版本的缓存清掉。

【回复】你这不就是说用户A在下单时,通知下用户B说我先下完单,写完mysql以及更新完缓存后你再操作?并发环境本来就是需要考虑一切不合理不应该出现的场景
風鈴玉秀:
加一个技术总是有很多小毛病要解决,我们太难了

红鲤驴233:
为什么up讲的跟别人讲的不一样呢,别人都是先删缓存,再改数据库,再延迟改缓存。别人的解释是如果先改数据库再改缓存,那别人之前读数据库,之后改缓存的线程会导致缓存不一致。但是我感觉第一次删除并不能解决这个问题,解决这个问题的是延迟,但是他们说延迟是为了主从复制。我感觉up是对的,但是跟别人不一样。

虾捣拾:
不明白,每次都要保证删除redis里的数据,刚开始的条件怎么发生呢,就是那个如果redis里面存在数据就直接返回,一直被redis删除,redis里怎么还能有数据呢?

Anti心:
小商城应用,限时抢购商品场景:考虑到会出现频繁的读写,使用CAP保证一致性,没有延迟双删(因为考虑到写会很快覆盖上);同时考虑避免大流量,使用了令牌限流策略。不知道可还行[微笑]

科技猎手 编程 阿里 面试 大厂 缓存 架构 redis

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!