当前位置: 首页 >文章 > 美团面试题:缓存一致性,我是这么回答的!
收藏
分享

美团面试题:缓存一致性,我是这么回答的!

举报小虎转载君小虎转载君发布于 2021-05-24789阅读0点赞
如果缓存设置了过期时间,那么上述的所有不一致情况都只是暂时的。...

人生本就是苦还是只有童年苦?生命就是如此!

-----这个杀手不太冷

一道之前的面试题:

如何保证缓存和数据库的一致性?

来自:社招一年半面经分享(含阿里美团头条京东滴滴)

下面介绍几种方案(大家回答的时候最好根据自己的业务,结合下面的方案)

文章较长,可以点赞在看


方案分析
更新缓存策略方式常见的有下面几种:

1.先更新缓存,再更新数据库
2.先更新数据库,再更新缓存
3.先删除缓存,再更新数据库
4.先更新数据库,再删除缓存


下面一一介绍!

方案一:更新缓存,更新数据库

这种方式可轻易排除,因为如果先更新缓存成功,但是数据库更新失败,则肯定会造成数据不一致。

方案二:更新数据库,更新缓存

这种缓存更新策略俗称双写,存在问题是:并发更新数据库场景下,会将脏数据刷到缓存


举例:如果在两个操作之间数据库和缓存又被后面请求修改,此时再去更新缓存已经是过期数据了。

方案三:删除缓存,更新数据库

存在问题:更新数据库之前,若有查询请求,会将脏数据刷到缓存


举例:如果在两个操作之间发生了数据查询,那么会有旧数据放入缓存。

该方案会导致请求数据不一致

如果同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:

请求A进行写操作,删除缓存

请求B查询发现缓存不存在

请求B去数据库查询得到旧值

请求B将旧值写入缓存

请求A将新值写入数据库

上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。

方案四:更新数据库,删除缓存


存在问题:在更新数据库之前有查询请求,并且缓存失效了,会查询数据库,然后更新缓存。如果在查询数据库和更新缓存之间进行了数据库更新的操作,那么就会把脏数据刷到缓存


举例:如果在查询数据库和放入缓存这两个操作中间发生了数据更新并且删除缓存,那么会有旧数据放入缓存。


假设有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生

缓存刚好失效

请求A查询数据库,得一个旧值

请求B将新值写入数据库

请求B删除缓存

请求A将查到的旧值写入缓存

如果发生上述情况,确实是会发生脏数据。但是发生上述情况有一个先天性条件,就是写数据库操作比读数据库操作耗时更短

不过数据库的读操作的速度远快于写操作的


因此这一情形很难出现。


方案对比

方案1和方案2的共同缺点:

并发更新数据库场景下,会将脏数据刷到缓存,但一般并发写的场景概率都相对小一些;

线程安全角度,会产生脏数据,比如:

线程A更新了数据库
线程B更新了数据库
线程B更新了缓存
线程A更新了缓存


方案3和方案4的共同缺点:

不管采用哪种顺序,2种方式都是存在一些问题的:

主从延时问题:不管是先删除还是后删除,数据库主从延时可能导致脏数据的产生。
缓存删除失败:如果缓存删除失败,则都会产生脏数据。
问题解决思路:延迟双删,添加重试机制,下面介绍!

更新缓存还是删除缓存?


1.更新缓存缓存需要有一定的维护成本,而且会存在并发更新的问题

2.写多读少的情况下,读请求还没有来,缓存以及被更新很多次,没有起到缓存的作用

3.放入缓存的值可能是经过复杂计算的,如果每次更新,都计算写入缓存的值,浪费性能的

删除缓存优点:简单、成本低,容易开发;缺点:会造成一次cache miss

如果更新缓存开销较小并且读多写少,基本不会有写并发的时候可以才用更新缓存,否则通用做法还是删除缓存。


总结

推荐方案

延迟双删
采用更新前后双删除缓存策略

先淘汰缓存

再写数据库

休眠1秒,再次淘汰缓存

大家应该评估自己的项目的读数据业务逻辑的耗时。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上即可。

这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

问题及解法:

1、同步删除,吞吐量降低如何处理

将第二次删除作为异步的,提交一个延迟的执行任务

2、解决删除失败的方式:

添加重试机制,例如:将删除失败的key,写入消息队列;但对业务耦合有些严重;

延时工具可以选择:

最普通的阻塞Thread.currentThread().sleep(1000);

Jdk调度线程池,quartz定时任务,利用jdk自带的delayQueue,netty的HashWheelTimer,Rabbitmq的延时队列,等等

实际场景
我们有个商品中心的场景,是读多写少的服务,并且写数据会发送MQ通知下游拿数据,这样就需要严格保证缓存和数据库的一致性,需要提供高可靠的系统服务能力。

写缓存策略
1.缓存key设置失效时间
2.先DB操作,再缓存失效
3.写操作都标记key(美团中间件)强制走主库
4.接入美团中间件监听binlog(美团中间件)变化的数据在进行兜底,再删除缓存

读缓存策略
1.先判断是否走主库
2.如果走主库,则使用标记(美团中间件)查主库
3.如果不是,则查看缓存中是否有数据
4.缓存中有数据,则使用缓存数据作为结果
5.如果没有,则查DB数据,再写数据到缓存

注意
关于缓存过期时间的问题

如果缓存设置了过期时间,那么上述的所有不一致情况都只是暂时的。

但是如果没有设置过期时间,那么不一致问题就只能等到下次更新数据时解决。

所以一定要设置缓存过期时间。


本文原创,未经作者允许不可转载!
更多内容,欢迎关注作者微信公众号: 月伴飞鱼!


0条评论
别默默看啦~登录/注册一起参与讨论吧~

暂无评论

请选择举报理由

违反法律法规

侵犯个人权益

有害网站环境

更多训练营>>

为你推荐 · 训练营(全勤打卡报名费全额返累计全额返用户133,746人)

【5月】零基础动态表情包创作训练营
距离开班仅剩3天53人已报名
【5月】7天轻松入门C4D小练习
距离开班仅剩7天26人已报名
【6月】7天轻松入门C4D小练习
距离开班仅剩28天0人已报名
猜你喜欢
特惠
充值
7折购
今日还在继续学习的你,太棒了!
7
折扣券可用于
年费无限VIP
立 即
使 用
此活动优惠不可与其他活动叠加使用
有效期:000000
消息
登录即可查看消息记录
建议
意见
官方
客服
在线咨询客服热线

您可以与在线客服进行沟通获得帮助

工作日:9:00~22:00节假日:9:00~18:00

联系在线客服

您可以电话联系客服进行沟通获得帮助

工作日:9:30~18:30

400-862-9191
虎课
积分
免费学习90000+个教程!
配套素材、源文件一键下载!
昨日学员已学习了38,686
并提交了140份作业!
登录后立即学习!
loading
微信扫码关注即可登录
您需要同意协议才可以进行登录
登录虎课网,每天免费学课程全站 90000+ 视频会员教程 | 每日可免费学 1
为确保账户信息安全
请先进行真实姓名验证后进行充值付款
立即验证