如何减少缓存删除 / 更新的失败?
admin
2024-02-07 13:24:45

万一删除缓存这一步因为服务重启没有执行,或者 Redis 临时不可用导致删除缓存失败了,就会有一个较长的时间(缓存的剩余过期时间)是数据不一致的。

那我们有没有什么手段来减少这种不一致的情况出现呢?这时候借助一个可靠的消息中间件就是一个不错的选择。

因为消息中间件有 ATLEAST-ONCE 的机制,如下图所示。

我们把删除 Redis 的请求以消费 MQ 消息的手段去失效对应的 Key 值,如果 Redis 真的存在异常导致无法删除成功,我们依旧可以依靠 MQ 的重试机制来让最终 Redis 对应的 Key 失效。

而你们或许会问,极端场景下,是否存在更新数据库后 MQ 消息没发送成功,或者没机会发送出去机器就重启的情况?

这个场景的确比较麻烦,如果 MQ 使用的是 RocketMQ,我们可以借助 RocketMQ 的事务消息,来让删除缓存的消息最终一定发送出去。而如果你没有使用 RocketMQ,或者你使用的消息中间件并没有事务消息的特性,则可以采取消息表的方式让更新数据库和发送消息一起成功。事实上这个话题比较大了,我们不在这里展开。

如何处理复杂的多缓存场景?

有些时候,真实的缓存场景并不是数据库中的一个记录对应一个 Key 这么简单,有可能一个数据库记录的更新会牵扯到多个 Key 的更新。还有另外一个场景是,更新不同的数据库的记录时可能需要更新同一个 Key 值,这常见于一些 App 首页数据的缓存。

我们以一个数据库记录对应多个 Key 的场景来举例。

假如系统设计上我们缓存了一个粉丝的主页信息、主播打赏榜 TOP10 的粉丝、单日 TOP 100 的粉丝等多个信息。如果这个粉丝注销了,或者这个粉丝触发了打赏的行为,上面多个 Key 可能都需要更新。只是一个打赏的记录,你可能就要做:

updateMySQL();//更新数据库一条记录
deleteRedisKey1();//失效主页信息的缓存
updateRedisKey2();//更新打赏榜TOP10
deleteRedisKey3();//更新单日打赏榜TOP100

这就涉及多个 Redis 的操作,每一步都可能失败,影响到后面的更新。甚至从系统设计上,更新数据库可能是单独的一个服务,而这几个不同的 Key 的缓存维护却在不同的 3 个微服务中,这就大大增加了系统的复杂度和提高了缓存操作失败的可能性。最可怕的是,操作更新记录的地方很大概率不只在一个业务逻辑中,而是散发在系统各个零散的位置。

针对这个场景,解决方案和上文提到的保证最终一致性的操作一样,就是把更新缓存的操作以 MQ 消息的方式发送出去,由不同的系统或者专门的一个系统进行订阅,而做聚合的操作。如下图:

不同业务系统订阅 MQ 消息单独维护各自的缓存 Key

专门更新缓存的服务订阅 MQ 消息维护所有相关 Key 的缓存操作

相关内容

热门资讯

从哈尔滨到长白山闺蜜5天4晚天... 从哈尔滨到长白山闺蜜5天4晚天池+延吉边境:拍照打卡真实体验 一、出发前的纠结:比老板还难搞的攻略,...
搭上低空经济、AI文旅?两连板... 来源:e公司 桂林旅游(000978)回应市场热点。 9月8日,桂林旅游再度涨停,斩获2连板。当天晚...
八达岭长城国庆怎么去最省心?坐... 八达岭长城是来北京必去的景点之一,尤其是第一次来北京的游客。但国庆期间去八达岭,最大的挑战不是爬长城...
秋日睦邻游园会热闹开锣!居民重... (来源:上观新闻) 近日,殷行街道包头路社区睦邻活动室里,举办了一场秋日睦邻趣味游园会,辖区居民、户...
带父母去长白山怎么玩?3天2晚... 带父母去长白山怎么玩?3天2晚天池攻略,有些坑帮你们踩过了 一句话总结:这次带父母去长白山,我选了黑...