上个月618全链路压测那天,我在会议室盯着监控屏,看着Redis的内存使用率稳稳停在62%,刚喝了一口冰美式,群里运维的消息直接弹出来——商品库的CPU冲到98%了,所有详情页接口全超时。
查了半小时才找到原因。负责商品模块的小伙子图省事,把所有商品缓存的过期时间统一设成了30分钟,压测前批量导入的缓存,到点了齐刷刷全失效,几万请求顺着网络直接砸到数据库上,连个缓冲都没有。
这事之后我把之前攒的所有缓存相关的笔记全翻出来,发现之前踩的坑,半本笔记都写不完。
别上来就抄大厂的过期时间配置
很多技术博客上来就甩个公式,说Redis的过期时间设成多少最优,根本不管你自己的业务场景是啥。
我们之前就踩过统一TTL的坑,所有key同生共死,到点集体消失,这不就是典型的缓存雪崩吗。之前看别人的方案说,只要给过期时间加随机偏移就行——对,但是没人说过,偏移量要结合你的业务峰值来算。比如我们商品模块的缓存基础TTL是1800秒,每个key额外加0到300秒的随机数,算下来所有缓存的失效时间会均匀分散在25分钟到35分钟这个区间里,哪怕同一时间导入的key,也不会在同一秒集体过期。

说起来好笑,之前还有个同事觉得既然要随机,那偏移量设大点,直接加1800秒,让TTL在30分钟到1小时之间晃,结果压测的时候发现,那些刚上架的新品,缓存已经存了40分钟了,明明还在流量高峰,结果提前过期,还是漏了一堆请求到数据库。
说白了,随机偏移不是拍脑袋定数字,你得算清楚自己的数据库最多能扛多少漏过来的流量,再倒推偏移的范围。别信那些吹得神乎其神的理论。谁要是再跟我说缓存配置可以一套参数打天下,我直接把监控截图甩他脸上。
哦对了,还有个容易被忽略的点:别把什么数据都往缓存里塞。上次运营提需求,说要把用户的每次浏览记录都存到Redis里,方便用户回看。我们算下账,一个用户一天刷100条内容,一百万用户就是一亿条key,这部分数据写多读少,大部分用户根本不会回头翻历史,占了快一半的Redis内存,真的纯纯浪费。缓存是用来存高频访问的热数据的,不是当万能存储桶用的。
穿透和击穿,真不是靠加个空值就能解决的
之前碰到过一次恶意攻击,有人写脚本挨个试不存在的商品ID,从1000000开始往上数,一秒钟发两百个请求,全是查数据库里根本不存在的商品。
一开始大家说这简单,把查不到的空值也缓存上,TTL设个1分钟就行。结果上线不到三天,客诉炸了——有个商品被运营临时下架,缓存了空值,半小时后运营把商品重新上架,用户点进去还是显示”商品不存在”,查了日志才发现,那个空值的TTL还没到,根本没人主动删。

后来我们改了流程:首先在网关层加规则,所有商品ID必须在合法的数值范围内,不满足格式的请求直接拦在外面,根本到不了缓存层。然后空值缓存的TTL最多设30秒,而且业务侧做商品上下架、价格变更的时候,必须主动删掉对应key的空缓存,不能光等着TTL自动过期。
还有击穿的坑,就是那种单热点的key,比如某明星带火的一款链接,QPS能冲到十万级,刚好这个key的缓存过期的那一秒,几万个请求同时穿过去查数据库。之前有人说用分布式锁就行,结果锁的粒度没控制好,一个请求拿了锁去查数据库,其他请求全堵在等锁,接口响应直接从20毫秒涨到300毫秒,用户直接卡退。
我们现在的做法更简单:真正的超级热点key,根本不设过期时间。后台开个轻量的异步线程,每隔10分钟扫一次这些热点key的剩余TTL,只要低于5分钟就主动续期,从根源上不让它碰到过期的那一刻。虽然多占了几十兆内存,但是总比大促的时候接口超时强。
谁爱搞复杂的锁逻辑谁搞,我是不想再为了省那点内存,担线上故障的风险了。
缓存的一致性,从来没有百分百完美的方案
之前团队里有个刚毕业的研发,做需求的时候跟我掰扯了半小时,说缓存和数据库必须强一致,不然用户看到旧数据就是故障。
我当时问他,你要做强一致的话,每次更新数据库的时候,必须同步删缓存,还要等删成功了才能给用户返回结果,接口响应得多加多少延迟?他说延迟高没关系,一致最重要。
结果上线第一周就出问题:他那边删缓存的时候刚好碰到网络抖动,删失败了,导致用户改了收货地址,过了半小时点进去还是原来的地址,被用户投诉到客服那边。
说实话,大部分互联网业务,真的不需要什么强一致。用户晚个两秒看到最新的价格、最新的地址,根本不会有什么大问题,总比为了追那0.1%的一致性,把接口响应搞慢几百毫秒,用户直接流失强吧?
我们现在用的方案很朴素:更新数据库成功之后,先删一次缓存,然后往延迟队列里发个500毫秒的消息,等消息到了再删一次对应的缓存。说白了就是兜个底,把因为并发更新导致的脏缓存覆盖掉,最终一致性足够覆盖99%的业务场景了。
别钻牛角尖。对吧?
之前总有人说缓存策略是个特别高深的技术,要学透多少原理才能用好。其实真不是,大部分线上的缓存故障,根本不是原理没学透,就是图省事,抄了别人的配置,根本没结合自己的业务场景算过账。
稳比快重要。少踩坑比背多少八股文有用。