智汇 IT
城启新篇

分布式缓存一致性保障一线踩坑后的真实取舍

上周跟做电商的后端老哥在楼下抽烟,他刚因为缓存脏数据赔了小半个月绩效。就因为改了用户头像的接口,忘了清Redis里的用户信息缓存。

用户传完图,等半小时还显示旧头像。客服接了二十多通投诉,才反应过来是缓存没刷。

说白了,分布式缓存一致性保障这事,从来不是教科书上写的那套“Cache Aside”就能打天下的。

先搞懂你要的到底是哪种“一致”

上来就追强一致的,多半是没被线上故障毒打过。

你要真要求所有节点同时看到最新值,那你直接上分布式事务多好,要缓存干嘛?

缓存本来就是拿一致性换性能的玩意儿。99%的业务场景,根本不需要强一致,只要最终一致,而且这个最终的时间窗口,能被用户接受就行。

比如商品详情页,你晚个3秒展示新价格,没人会投诉。但要是库存数晚3秒,用户下了单扣不了钱,那才是事故。

麻烦在于,没人会提前告诉你这个时间窗口到底能放多宽。你得自己摸。之前有个后端跟我吐槽,他花了三天排查线上的脏数据问题,最后发现就是毫秒级的竞态交叉,压测根本复现不出来,只能靠打日志抓了一周才逮到那个时间点。

分布式缓存不同一致性级别延迟对比示意图
分布式缓存不同一致性级别延迟对比示意图

很多人最开始学缓存一致性,学的都是经典的Cache Aside模式:读的时候先查缓存,没命中就查数据库,再把值写回缓存;写的时候先更新数据库,再删除缓存。

这模式能用,但藏着两个致命的竞态条件。最常见的那个:读请求缓存miss,正准备读数据库,这时候另一个写请求更新了数据库,删了缓存,结果刚才那个读请求拿着旧的数据库值,回头把旧值写回了缓存。

这坑太隐蔽了。

你压测的时候根本复现不出来。得刚好在毫秒级的窗口里,两个线程交叉操作,线上流量大了,指不定哪天就蹦出来。

常见的解法是延迟双删:写完数据库删完缓存,等个几百毫秒,再删一次。但这个延迟时间设多少?没人能给你准数。设短了没用,设长了脏数据留的时间更久。说白了就是个兜底的补丁,不是根治的方案。

别迷信所有写操作都走同一条路

上个月见个做本地生活的团队,所有商家改门店信息的操作,都同步走Redis删缓存。

赶上商家中午批量改营业时间的高峰,Redis的QPS直接飙到平时的5倍。数据库写完了,缓存删除请求堵在网络队列里,半天发不出去。用户刷到的还是上周的营业时间,跑过去发现店没开,投诉直接炸了。

后来他们把非核心字段的缓存删除,改成走消息队列异步删。核心字段,比如门店地址、营业时间,还是同步删。非核心的,比如商家的宣传图、简介,异步删,晚个几秒根本没人在意。

这里的核心是,你得把缓存要承载的字段做优先级拆分,不能所有内容都要同一个一致性级别。

有人说那我直接用Canal订阅binlog,更新完数据库就自动触发缓存删除,不就没竞态了?

是没竞态了。但你要多维护一套Canal集群,多一套消息队列链路。出了问题,排查链路比原来长三倍。上次有个团队的Canal客户端挂了,堆了十万条binlog没消费,缓存脏了俩小时才发现。没人盯的时候,这种方案就是定时炸弹。

基于binlog同步缓存更新链路流程图
基于binlog同步缓存更新链路流程图

你以为的兜底方案,可能才是最大的坑

很多人给缓存设了个过期时间,觉得反正过期了就会重新读数据库,怕啥。

是,过期时间是兜底的。但你要是给热点数据设了个1小时的过期时间,碰上刚才说的那种binlog挂了的情况,那就是1小时的脏数据。

我见过最离谱的,有人把商品库存的缓存过期时间设成了24小时。大促的时候库存改了,缓存没刷,用户下了单才发现没货。赔了一堆优惠券。

说白了,过期时间是最后一道防线,不是你搞不定一致性的挡箭牌。

还有人搞分布式锁,更新缓存的时候加锁,保证顺序。结果锁的粒度设太粗,整个key的读写都堵在锁上,缓存的性能优势直接没了。那还要缓存干嘛?直接读数据库得了。

这里的取舍从来不是非黑即白的。你要性能,就得接受一定概率的脏数据。你要绝对的一致,就得接受性能折损个七八成。没有什么银弹。

对了,上次那个踩头像坑的老哥,后来改的方案是啥?他把用户头像的缓存过期时间设成了5分钟。写操作的时候,同步删缓存。然后加了个监控,只要同一个用户的头像缓存,在5分钟内被连续更新两次,就触发告警。

就这么简单。没有上复杂的分布式事务,没有搞什么全局一致性协议。因为用户头像这东西,晚个5分钟更新,根本没人会真的生气。总比你为了那毫秒级的一致性,把整个链路搞的复杂到没人能维护强。

分布式缓存一致性保障这事,从来没有标准答案。你得盯着自己的业务场景算代价。别抄别人的作业。别人的核心链路,可能是你的边缘场景。别人能接受的几秒延迟,可能会让你赔到哭。

就这么简单。

免责声明:市场有风险,选择需谨慎!此文仅供参考,不作买卖依据。如有侵权请联系删除。
文章名称:分布式缓存一致性保障一线踩坑后的真实取舍
文章链接:https://m.itcdj.com/it/294.html